rlirc 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/INSTALL ADDED
@@ -0,0 +1,14 @@
1
+ De-Compress archive and enter its top directory.
2
+ Then type:
3
+
4
+ $ ruby setup.rb config
5
+ $ ruby setup.rb setup
6
+ ($ su)
7
+ # ruby setup.rb install
8
+
9
+ You can also install files into your favorite directory
10
+ by supplying setup.rb some options. Try "ruby setup.rb --help".
11
+
12
+ There is also a Rakefile for generating packages, rdoc, ...
13
+ just type rake in the top directory to see a list of options
14
+
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2004, Roeland Moors
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+ 1. Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+ 3. The name of the author may not be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19
+ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
26
+
data/README ADDED
@@ -0,0 +1,29 @@
1
+ = rlirc README
2
+
3
+ rlirc is a replacement for irexec (lirc)
4
+
5
+ == Requirements
6
+
7
+ * ruby 1.8
8
+ * lirc
9
+
10
+ == Install
11
+
12
+ :include: INSTALL
13
+
14
+ == Documentation
15
+
16
+ http://rlirc.rubyforge.org
17
+
18
+ == Support
19
+
20
+ The homepage is at http://rlirc.rubyforge.org.
21
+ Go to the project page for more information.
22
+
23
+ Feel free to submit commits or feature requests.
24
+
25
+ == License
26
+
27
+ Gnucap-Ruby is available under a BSD license
28
+
29
+ :include: LICENSE
@@ -0,0 +1,106 @@
1
+ # Rakefile for rlirc
2
+
3
+ require 'rubygems'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+ require 'rake/clean'
7
+
8
+ #############
9
+ # rake help #
10
+ #############
11
+
12
+ desc "Default Task (show this help)"
13
+ task :default => :help
14
+
15
+ desc "Show this help"
16
+ task :help do
17
+ sh "rake --task"
18
+ end
19
+
20
+ ################
21
+ # rake version #
22
+ ################
23
+
24
+ version = `grep 'REVISION =' #{Dir.pwd}/bin/rlirc`
25
+ PKG_VERSION = version.split('=')[1].chomp.delete(' ').delete("'")
26
+ PKG_NAME = 'rlirc'
27
+
28
+ desc "Show version of rlirc"
29
+ task :version do
30
+ puts "Version: #{PKG_VERSION}"
31
+ end
32
+
33
+ ################
34
+ # rake install #
35
+ ################
36
+
37
+ desc "Info about installing rlirc"
38
+ task :install do
39
+ install_info = <<-EOS
40
+ Typical installation procedure is:
41
+ $ ruby setup.rb config
42
+ $ ruby setup.rb setup
43
+ # ruby setup.rb install (may require root privilege)
44
+ Try 'ruby setup.rb --help' for detailed usage.
45
+ EOS
46
+
47
+ puts install_info
48
+
49
+ end
50
+
51
+ #############
52
+ # rake rdoc #
53
+ #############
54
+
55
+ Rake::RDocTask.new do |rd|
56
+ rd.rdoc_dir = 'rdoc'
57
+ rd.main = 'README'
58
+ rd.rdoc_files.include('README', 'LICENSE', 'lib/**/*.rb')
59
+ rd.options << '-S'
60
+ end
61
+
62
+ #################
63
+ # rake packages #
64
+ #################
65
+
66
+ PKG_FILES = FileList[
67
+ 'setup.rb',
68
+ '[A-Z]*',
69
+ 'lib/**/*.rb',
70
+ 'data/**/*.rb',
71
+ 'bin/**/*',
72
+ 'ext/**/*'
73
+ ]
74
+
75
+ gemspec = Gem::Specification.new do |s|
76
+ s.author = "Roeland Moors"
77
+ s.autorequire = 'rlirc'
78
+ s.bindir = 'bin'
79
+ s.default_executable = 'rlirc'
80
+ s.add_dependency('libxosd2-ruby', '>= 0.4')
81
+ s.description = "a replacement for irexec and irxevent from lirc"
82
+ s.email = "roelandmoors@telenet.be"
83
+ s.executables = ['rlirc']
84
+ s.extensions << "ext/xevent/extconf.rb"
85
+ s.extra_rdoc_files = ['README']
86
+ s.files = PKG_FILES.to_a
87
+ s.has_rdoc = true
88
+ s.homepage = "http://rlirc.rubyforge.org"
89
+ s.name = PKG_NAME
90
+ #s.platform
91
+ #s.rdoc_options
92
+ s.require_path = 'lib'
93
+ s.required_ruby_version = '>= 1.8.1'
94
+ s.requirements << 'X dev libs'
95
+ s.rubyforge_project = "rlirc"
96
+ s.summary = "a replacement for irexec and irxevent from lirc"
97
+ #s.test_files
98
+ s.version = PKG_VERSION
99
+ end
100
+
101
+
102
+ Rake::GemPackageTask.new(gemspec) do |pkg|
103
+ pkg.need_zip = false
104
+ pkg.need_tar = true
105
+ end
106
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rlirc'
4
+
5
+ REVISION = '0.3.1'
6
+
7
+ begin
8
+ Rlirc.new(ARGV)
9
+ rescue => e
10
+ $stderr.puts <<EOS
11
+ -----------------------
12
+ Rlirc just crashed
13
+ -----------------------
14
+ Timestamp: #{Time.now}
15
+ Message: #{e.message}
16
+ Backtrace:
17
+ #{e.backtrace.join("\n")}
18
+ Release: #{REVISION}
19
+ Uname -a: #{`uname -a`.chomp}
20
+ EOS
21
+ exit 1
22
+ end
23
+
24
+
25
+
@@ -0,0 +1,123 @@
1
+ require 'rlirc'
2
+
3
+ # only needed if you need OSD
4
+ require 'rlirc/osd'
5
+
6
+ # aumix functions
7
+ require 'rlirc/aumix'
8
+
9
+ # send x events
10
+ require 'rlirc/xevent'
11
+
12
+ # lirc device
13
+ $device = '/dev/lircd'
14
+
15
+ # show debug information
16
+ $debug = false
17
+
18
+ # prevents unwanted repeated presses
19
+ # (under construction)
20
+ $delay = 0
21
+
22
+ # osd settings, look at these webpages for other options:
23
+ # http://rubyforge.org/projects/libxosd-ruby/
24
+ # http://ldots.org/xosd-guide/using_libxosd.html
25
+ $osd.timeout = 2
26
+
27
+
28
+ # This is the default class
29
+ class ModeMain < Mode
30
+ def initialize
31
+ end
32
+
33
+ def button_tv
34
+ change_mode(ModeTV)
35
+ end
36
+
37
+ def button_radio
38
+ change_mode(ModeRadio)
39
+ end
40
+
41
+
42
+ end
43
+
44
+ # a button defined here is always executed
45
+ class ModeGlobal < Mode
46
+ def button_volup
47
+ `aumix -v+5`
48
+ end
49
+
50
+ def button_volup_repeat(count)
51
+ button_volup
52
+ end
53
+
54
+ def button_voldown
55
+ `aumix -v-5`
56
+ end
57
+
58
+ def button_voldown_repeat(count)
59
+ button_voldown
60
+ end
61
+
62
+ def button_mute
63
+ aumix_mute_toggle
64
+ end
65
+ end
66
+
67
+ class ModeRadio < Mode
68
+ def initialize
69
+ button_1
70
+ end
71
+
72
+ def button_radio
73
+ `radio -qm`
74
+ end_mode # == change_mode(ModeMain)
75
+ end
76
+
77
+ def button_1
78
+ osd "StuBru"
79
+ `radio -qf 96.6`
80
+ end
81
+
82
+ def button_2
83
+ osd "Donna"
84
+ `radio -qf 101.7`
85
+ end
86
+
87
+ def button_tv
88
+ `radio -qm`
89
+ change_mode(ModeTV)
90
+ end
91
+ end
92
+
93
+ class ModeTV < Mode
94
+ def initialize
95
+ system("tvtime &")
96
+ end
97
+
98
+ def button_tv
99
+ `tvtime-command QUIT`
100
+ end_mode # == change_mode(ModeMain)
101
+ end
102
+
103
+ def button_radio
104
+ `tvtime-command QUIT`
105
+ change_mode(ModeRadio)
106
+ end
107
+
108
+ def button_chup
109
+ `tvtime-command UP`
110
+ end
111
+
112
+ def button_chdown
113
+ `tvtime-command DOWN`
114
+ end
115
+
116
+ def number(nr)
117
+ `tvtime-command CHANNEL_#{nr}`
118
+ end
119
+
120
+ def button_full_screen
121
+ xevent('Key f tvtime')
122
+ end
123
+ end
@@ -0,0 +1,2 @@
1
+ extconf.rb
2
+ xevent.c
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ if find_library("X11", "XOpenDisplay", "/usr/X11/lib",
4
+ "/usr/X11R6/lib", "/usr/openwin/lib")
5
+ then
6
+ create_makefile("xevent")
7
+ else
8
+ puts "No X support available"
9
+ end
@@ -0,0 +1,574 @@
1
+ /*
2
+ * The most of this is code is from irxevent.c in the lirc package
3
+ * I used the code from lirc version 0.7.0pre7.
4
+ * This means this code is under the same license (GPL)
5
+ *
6
+ * Here is the copyright stuff from the original file:
7
+ * ---
8
+ * Heinrich Langos <heinrich@null.net>
9
+ * small modifications by Christoph Bartelmus <lirc@bartelmus.de>
10
+ *
11
+ * irxevent is based on irexec (Copyright (C) 1998 Trent Piepho)
12
+ * and irx.c (no copyright notice found)
13
+ * ---
14
+ *
15
+ * Here is the changelog
16
+ *
17
+ * 0.1: (Roeland Moors)
18
+ * removed the lirc config stuff
19
+ * added ruby stuff
20
+ */
21
+
22
+ #ifdef HAVE_CONFIG_H
23
+ # include <config.h>
24
+ #endif
25
+
26
+ #include <errno.h>
27
+ #include <unistd.h>
28
+ #include <getopt.h>
29
+ #include <stdarg.h>
30
+ #include <stdio.h>
31
+ #include <stdlib.h>
32
+ #include <string.h>
33
+ #include <sys/socket.h>
34
+ #include <sys/un.h>
35
+ #include <sys/stat.h>
36
+ #include <sys/types.h>
37
+
38
+ #include <X11/Xlib.h>
39
+ #include <X11/Xutil.h>
40
+ #include <sys/time.h>
41
+ #include <unistd.h>
42
+
43
+ #include <ruby.h>
44
+
45
+ #define DEBUG
46
+ #ifdef DEBUG
47
+ void debugprintf(char *format_str, ...)
48
+ {
49
+ va_list ap;
50
+ va_start(ap,format_str);
51
+ vfprintf(stderr,format_str,ap);
52
+ va_end(ap);
53
+ }
54
+ #else
55
+ void debugprintf(char *format_str, ...)
56
+ {
57
+ }
58
+ #endif
59
+
60
+
61
+ struct keymodlist_t {
62
+ char *name;
63
+ Mask mask;
64
+ };
65
+ static struct keymodlist_t keymodlist[]=
66
+ {
67
+ {"SHIFT", ShiftMask},
68
+ {"CAPS", LockMask},
69
+ {"CTRL", ControlMask},
70
+ {"ALT", Mod1Mask},{"META", Mod1Mask},
71
+ {"NUMLOCK", Mod2Mask},
72
+ {"MOD3", Mod3Mask}, /* I don't have a clue what key maps to this. */
73
+ {"MOD4", Mod4Mask}, /* I don't have a clue what key maps to this. */
74
+ {"SCRLOCK", Mod5Mask},
75
+ {NULL,0},
76
+ };
77
+
78
+ const char *key_delimiter ="-";
79
+ const char *active_window_name ="CurrentWindow";
80
+ const char *root_window_name ="RootWindow";
81
+
82
+
83
+ char *progname;
84
+ Display *dpy;
85
+ Window root;
86
+ XEvent xev;
87
+ Window w,subw;
88
+
89
+ Time fake_timestamp()
90
+ /*seems that xfree86 computes the timestamps like this */
91
+ /*strange but it relies on the *1000-32bit-wrap-around */
92
+ /*if anybody knows exactly how to do it, please contact me */
93
+ {
94
+ int tint;
95
+ struct timeval tv;
96
+ struct timezone tz; /* is not used since ages */
97
+ gettimeofday(&tv,&tz);
98
+ tint=(int)tv.tv_sec*1000;
99
+ tint=tint/1000*1000;
100
+ tint=tint+tv.tv_usec/1000;
101
+ return (Time)tint;
102
+ }
103
+
104
+ Window find_window(Window top,char *name)
105
+ {
106
+ char *wname,*iname;
107
+ XClassHint xch;
108
+ Window *children,foo;
109
+ int revert_to_return;
110
+ unsigned int nc;
111
+ if (!strcmp(active_window_name,name)){
112
+ XGetInputFocus(dpy, &foo, &revert_to_return);
113
+ return(foo);
114
+ } else if (!strcmp(root_window_name,name)){
115
+ return(root);
116
+ }
117
+ /* First the base case */
118
+ if (XFetchName(dpy,top,&wname)){
119
+ if (!strncmp(wname,name,strlen(name))) {
120
+ XFree(wname);
121
+ debugprintf("found it by wname 0x%x \n",top);
122
+ return(top); /* found it! */
123
+ };
124
+ XFree(wname);
125
+ };
126
+
127
+ if(XGetIconName(dpy,top,&iname)){
128
+ if (!strncmp(iname,name,strlen(name))) {
129
+ XFree(iname);
130
+ debugprintf("found it by iname 0x%x \n",top);
131
+ return(top); /* found it! */
132
+ };
133
+ XFree(iname);
134
+ };
135
+
136
+ if(XGetClassHint(dpy,top,&xch)) {
137
+ if(!strcmp(xch.res_class,name)) {
138
+ XFree(xch.res_name); XFree(xch.res_class);
139
+ debugprintf("res_class '%s' res_name '%s' 0x%x \n", xch.res_class,xch.res_name,top);
140
+ return(top); /* found it! */
141
+ };
142
+ if(!strcmp(xch.res_name,name)) {
143
+ XFree(xch.res_name); XFree(xch.res_class);
144
+ debugprintf("res_class '%s' res_name '%s' 0x%x \n", xch.res_class,xch.res_name,top);
145
+ return(top); /* found it! */
146
+ };
147
+ XFree(xch.res_name); XFree(xch.res_class);
148
+ };
149
+
150
+ if(!XQueryTree(dpy,top,&foo,&foo,&children,&nc) || children==NULL) {
151
+ return(0); /* no more windows here */
152
+ };
153
+
154
+ /* check all the sub windows */
155
+ for(;nc>0;nc--) {
156
+ top = find_window(children[nc-1],name);
157
+ if(top) break; /* we found it somewhere */
158
+ };
159
+ if(children!=NULL) XFree(children);
160
+ return(top);
161
+ }
162
+
163
+ Window find_sub_sub_window(Window top,int *x, int *y)
164
+ {
165
+ Window base;
166
+ Window *children,foo,target=0;
167
+ unsigned int nc,
168
+ rel_x,rel_y,width,height,border,depth,
169
+ new_x=1,new_y=1,
170
+ targetsize=1000000;
171
+
172
+ base=top;
173
+ if (!base) {return base;};
174
+ if(!XQueryTree(dpy,base,&foo,&foo,&children,&nc) || children==NULL) {
175
+ return(base); /* no more windows here */
176
+ };
177
+ debugprintf("found subwindows %d\n",nc);
178
+
179
+ /* check if we hit a sub window and find the smallest one */
180
+ for(;nc>0;nc--) {
181
+ if(XGetGeometry(dpy, children[nc-1], &foo, &rel_x, &rel_y,
182
+ &width, &height, &border, &depth)){
183
+ if ((rel_x<=*x)&&(*x<=rel_x+width)&&(rel_y<=*y)&&(*y<=rel_y+height)){
184
+ debugprintf("found a subwindow 0x%x +%d +%d %d x %d \n",children[nc-1], rel_x,rel_y,width,height);
185
+ if ((width*height)<targetsize){
186
+ target=children[nc-1];
187
+ targetsize=width*height;
188
+ new_x=*x-rel_x;
189
+ new_y=*y-rel_y;
190
+ /*bull's eye ...*/
191
+ target=find_sub_sub_window(target,&new_x,&new_y);
192
+ }
193
+ }
194
+ }
195
+ };
196
+ if(children!=NULL) XFree(children);
197
+ if (target){
198
+ *x=new_x;
199
+ *y=new_y;
200
+ return target;
201
+ }else
202
+ return base;
203
+ }
204
+
205
+
206
+
207
+ Window find_sub_window(Window top,char *name,int *x, int *y)
208
+ {
209
+ Window base;
210
+ Window *children,foo,target=0;
211
+ unsigned int nc,
212
+ rel_x,rel_y,width,height,border,depth,
213
+ new_x=1,new_y=1,
214
+ targetsize=1000000;
215
+
216
+ base=find_window(top, name);
217
+ if (!base) {return base;};
218
+ if(!XQueryTree(dpy,base,&foo,&foo,&children,&nc) || children==NULL) {
219
+ return(base); /* no more windows here */
220
+ };
221
+ debugprintf("found subwindows %d\n",nc);
222
+
223
+ /* check if we hit a sub window and find the smallest one */
224
+ for(;nc>0;nc--) {
225
+ if(XGetGeometry(dpy, children[nc-1], &foo, &rel_x, &rel_y,
226
+ &width, &height, &border, &depth)){
227
+ if ((rel_x<=*x)&&(*x<=rel_x+width)&&(rel_y<=*y)&&(*y<=rel_y+height)){
228
+ debugprintf("found a subwindow 0x%x +%d +%d %d x %d \n",children[nc-1], rel_x,rel_y,width,height);
229
+ if ((width*height)<targetsize){
230
+ target=children[nc-1];
231
+ targetsize=width*height;
232
+ new_x=*x-rel_x;
233
+ new_y=*y-rel_y;
234
+ /*bull's eye ...*/
235
+ target=find_sub_sub_window(target,&new_x,&new_y);
236
+ }
237
+ }
238
+ }
239
+ };
240
+ if(children!=NULL) XFree(children);
241
+ if (target){
242
+ *x=new_x;
243
+ *y=new_y;
244
+ return target;
245
+ }else
246
+ return base;
247
+ }
248
+
249
+
250
+ Window find_window_focused(Window top,char *name)
251
+ {
252
+ int tmp;
253
+ Window w, cur, *children, foo;
254
+ unsigned int n;
255
+
256
+
257
+ /* return the currently focused window if it is a direct match or a
258
+ subwindow of the named window */
259
+
260
+ if((w=find_window(top,name))) {
261
+ XGetInputFocus(dpy, &cur, &tmp);
262
+ debugprintf("current window: 0x%x named window: 0x%x\n",cur,w);
263
+
264
+ if( w == cur ) {
265
+ /* window matched */
266
+ return(cur);
267
+ }
268
+ else if(XQueryTree(dpy,w,&foo,&foo,&children,&n) && children!=NULL) {
269
+ /* check all the sub windows of named window */
270
+ for(;n>0;n--) {
271
+ if(children[n-1] == cur ) {
272
+ XFree(children);
273
+ return(cur);
274
+ }
275
+ }
276
+ XFree(children);
277
+ }
278
+ }
279
+
280
+ return(0);
281
+ }
282
+
283
+ void make_button(int button,int x,int y,XButtonEvent *xev)
284
+ {
285
+ xev->type = ButtonPress;
286
+ xev->display=dpy;
287
+ xev->root=root;
288
+ xev->subwindow=None;
289
+ xev->time=fake_timestamp();
290
+ xev->x=x;xev->y=y;
291
+ xev->x_root=1; xev->y_root=1;
292
+ xev->state=0;
293
+ xev->button=button;
294
+ xev->same_screen=True;
295
+
296
+ return;
297
+ }
298
+
299
+ void make_key(char *keyname,int x, int y,XKeyEvent *xev)
300
+ {
301
+ char *part, *part2;
302
+ struct keymodlist_t *kmlptr;
303
+
304
+ part2=malloc(128);
305
+
306
+ xev->type = KeyPress;
307
+ xev->display=dpy;
308
+ xev->root=root;
309
+ xev->subwindow = None;
310
+ xev->time=fake_timestamp();
311
+ xev->x=x; xev->y=y;
312
+ xev->x_root=1; xev->y_root=1;
313
+ xev->same_screen = True;
314
+
315
+ xev->state=0;
316
+ #ifdef HAVE_STRSEP
317
+ while ((part=strsep(&keyname, key_delimiter)))
318
+ #else
319
+ while ((part=strtok(keyname, key_delimiter)) && ((keyname=NULL)==NULL))
320
+ #endif
321
+ {
322
+ part2=strncpy(part2,part,128);
323
+ // debugprintf("- %s \n",part);
324
+ kmlptr=keymodlist;
325
+ while (kmlptr->name)
326
+ {
327
+ // debugprintf("-- %s %s \n", kmlptr->name, part);
328
+ if (!strcasecmp(kmlptr->name, part))
329
+ xev->state|=kmlptr->mask;
330
+ kmlptr++;
331
+ }
332
+ // debugprintf("--- %s \n",part);
333
+ }
334
+ // debugprintf("*** %s \n",part);
335
+ // debugprintf("*** %s \n",part2);
336
+ xev->keycode=XKeysymToKeycode(dpy,XStringToKeysym(part2));
337
+ debugprintf("state 0x%x, keycode 0x%x\n",xev->state, xev->keycode);
338
+ free(part2);
339
+ return ;
340
+ }
341
+
342
+ void sendfocus(Window w,int in_out)
343
+ {
344
+ XFocusChangeEvent focev;
345
+
346
+ focev.display=dpy;
347
+ focev.type=in_out;
348
+ focev.window=w;
349
+ focev.mode=NotifyNormal;
350
+ focev.detail=NotifyPointer;
351
+ XSendEvent(dpy,w,True,FocusChangeMask,(XEvent*)&focev);
352
+ XSync(dpy,True);
353
+
354
+ return;
355
+ }
356
+
357
+ void sendpointer_enter_or_leave(Window w,int in_out)
358
+ {
359
+ XCrossingEvent crossev;
360
+ crossev.type=in_out;
361
+ crossev.display=dpy;
362
+ crossev.window=w;
363
+ crossev.root=root;
364
+ crossev.subwindow=None;
365
+ crossev.time=fake_timestamp();
366
+ crossev.x=1;
367
+ crossev.y=1;
368
+ crossev.x_root=1;
369
+ crossev.y_root=1;
370
+ crossev.mode=NotifyNormal;
371
+ crossev.detail=NotifyNonlinear;
372
+ crossev.same_screen=True;
373
+ crossev.focus=True;
374
+ crossev.state=0;
375
+ XSendEvent(dpy,w,True,EnterWindowMask|LeaveWindowMask,(XEvent*)&crossev);
376
+ XSync(dpy,True);
377
+ return;
378
+ }
379
+
380
+ void sendkey(char *keyname,int x,int y,Window w,Window s)
381
+ {
382
+ make_key(keyname ,x,y,(XKeyEvent*)&xev);
383
+ xev.xkey.window=w;
384
+ xev.xkey.subwindow=s;
385
+
386
+ if (s) sendfocus(s,FocusIn);
387
+
388
+ XSendEvent(dpy,w,True,KeyPressMask,&xev);
389
+ xev.type = KeyRelease;
390
+ usleep(2000);
391
+ xev.xkey.time = fake_timestamp();
392
+ if (s) sendfocus(s,FocusOut);
393
+ XSendEvent(dpy,w,True,KeyReleaseMask,&xev);
394
+ XSync(dpy,True);
395
+ return;
396
+ }
397
+
398
+ void sendbutton(int button, int x, int y, Window w,Window s)
399
+ {
400
+ make_button(button,x,y,(XButtonEvent*)&xev);
401
+ xev.xbutton.window=w;
402
+ xev.xbutton.subwindow=s;
403
+ sendpointer_enter_or_leave(w,EnterNotify);
404
+ sendpointer_enter_or_leave(s,EnterNotify);
405
+
406
+ XSendEvent(dpy,w,True,ButtonPressMask,&xev);
407
+ XSync(dpy,True);
408
+ xev.type = ButtonRelease;
409
+ xev.xkey.state|=0x100;
410
+ usleep(1000);
411
+ xev.xkey.time = fake_timestamp();
412
+ XSendEvent(dpy,w,True,ButtonReleaseMask,&xev);
413
+ sendpointer_enter_or_leave(s,LeaveNotify);
414
+ sendpointer_enter_or_leave(w,LeaveNotify);
415
+ XSync(dpy,True);
416
+
417
+ return;
418
+ }
419
+
420
+
421
+ int check(char *s)
422
+ {
423
+ int d;
424
+ char *buffer;
425
+
426
+ buffer=malloc(strlen(s));
427
+ if(buffer==NULL)
428
+ {
429
+ fprintf(stderr,"%s: out of memory\n",progname);
430
+ return 0;
431
+ }
432
+
433
+ if(2!=sscanf(s,"Key %s Focus %s %s",buffer,buffer,buffer) &&
434
+ 2!=sscanf(s,"Key %s WindowID %i %s",buffer,&d,buffer) &&
435
+ 2!=sscanf(s,"Key %s Focus WindowID %i %s",buffer,&d,buffer) &&
436
+ 2!=sscanf(s,"Key %s %s %s",buffer,buffer,buffer) &&
437
+ 4!=sscanf(s,"Button %d %d %d Focus %s %s",&d,&d,&d,buffer,buffer) &&
438
+ 4!=sscanf(s,"Button %d %d %d WindowID %i %s",&d,&d,&d,&d,buffer) &&
439
+ 4!=sscanf(s,"Button %d %d %d Focus WindowID %i %s",&d,&d,&d,&d,buffer) &&
440
+ 4!=sscanf(s,"Button %d %d %d %s %s",&d,&d,&d,buffer,buffer) &&
441
+ 4!=sscanf(s,"xy_Key %d %d %s Focus %s %s",&d,&d,buffer,buffer,buffer) &&
442
+ 4!=sscanf(s,"xy_Key %d %d %s WindowID %i %s",&d,&d,buffer,&d,buffer) &&
443
+ 4!=sscanf(s,"xy_Key %d %d %s Focus WindowID %i %s",&d,&d,buffer,&d,buffer) &&
444
+ 4!=sscanf(s,"xy_Key %d %d %s %s",&d,&d,buffer,buffer))
445
+ {
446
+ fprintf(stderr,"%s: bad config string \"%s\"\n",progname,s);
447
+ free(buffer);
448
+ return 0;
449
+ }
450
+ free(buffer);
451
+ return 1;
452
+ }
453
+
454
+ void xevent_init()
455
+ {
456
+ dpy=XOpenDisplay(NULL);
457
+ if(dpy==NULL) {
458
+ fprintf(stderr,"Can't open DISPLAY.\n");
459
+ }
460
+ root=RootWindow(dpy,DefaultScreen(dpy));
461
+ }
462
+
463
+ int xevent(char *cmd)
464
+ {
465
+ char keyname[128];
466
+ int pointer_button,pointer_x,pointer_y;
467
+ char windowname[64];
468
+ int WindowID;
469
+
470
+ *windowname=0;
471
+
472
+ if(2==sscanf(cmd,"Key %s Focus WindowID %i",keyname,&WindowID) ||
473
+ 4==sscanf(cmd,"Button %d %d %d Focus WindowID %i",
474
+ &pointer_button,&pointer_x,&pointer_y,&WindowID) ||
475
+ 4==sscanf(cmd,"xy_Key %d %d %s Focus WindowID %i",
476
+ &pointer_x,&pointer_y,keyname,&WindowID) ||
477
+ 2==sscanf(cmd,"Key %s Focus %s",keyname,windowname) ||
478
+ 4==sscanf(cmd,"Button %d %d %d Focus %s",
479
+ &pointer_button,&pointer_x,&pointer_y,windowname) ||
480
+ 4==sscanf(cmd,"xy_Key %d %d %s Focus %s",
481
+ &pointer_x,&pointer_y,keyname,windowname))
482
+ {
483
+ debugprintf("Focus\n");
484
+ /* focussed ? */
485
+ if(*windowname) {
486
+ WindowID=find_window_focused(root,windowname);
487
+ if(!WindowID) {
488
+ debugprintf("target window '%s' doesn't have focus\n",windowname);
489
+ return -1;
490
+ }
491
+ debugprintf("focused: %s\n",windowname);
492
+ } else {
493
+ Window cur;
494
+ int tmp;
495
+
496
+ XGetInputFocus(dpy, &cur, &tmp);
497
+ if(WindowID != cur) {
498
+ debugprintf("target window '0x%x' doesn't have focus\n",WindowID);
499
+ return -1;
500
+ }
501
+ debugprintf("focused: 0x%x\n",WindowID);
502
+ }
503
+ } else if(2==sscanf(cmd,"Key %s WindowID %i",keyname,&WindowID) ||
504
+ 4==sscanf(cmd,"Button %d %d %d WindowID %i",
505
+ &pointer_button,&pointer_x,&pointer_y,&WindowID) ||
506
+ 4==sscanf(cmd,"xy_Key %d %d %s WindowID %i",
507
+ &pointer_x,&pointer_y,keyname,&WindowID)) {
508
+ debugprintf("WindowID: 0x%x\n",WindowID);
509
+ /* WindowID passed */
510
+ } else if(2==sscanf(cmd,"Key %s %s",keyname,windowname) ||
511
+ 4==sscanf(cmd,"Button %d %d %d %s",
512
+ &pointer_button,&pointer_x,&pointer_y,windowname) ||
513
+ 4==sscanf(cmd,"xy_Key %d %d %s %s\n",
514
+ &pointer_x,&pointer_y,keyname,windowname)) {
515
+ debugprintf("name: %s\n",windowname);
516
+ WindowID=find_window(root,windowname);
517
+ }
518
+
519
+ switch(cmd[0])
520
+ {
521
+ case 'K': // Key
522
+ debugprintf("keyname: %s \t WindowID: 0x%x\n",keyname,WindowID);
523
+ debugprintf("%s\n",cmd);
524
+ sendkey(keyname,1,1,(Window)WindowID,0);
525
+ break;
526
+
527
+ case 'B': // Button
528
+ case 'x': // xy_Key
529
+ subw=find_sub_window(root,windowname,&pointer_x,&pointer_y);
530
+ if(subw) {
531
+ if (WindowID==subw) subw=0;
532
+ debugprintf("%s\n",cmd);
533
+ switch(cmd[0])
534
+ {
535
+ case 'B':
536
+ sendbutton(pointer_button,pointer_x,pointer_y,WindowID,subw);
537
+ break;
538
+ case 'x':
539
+ sendkey(keyname,pointer_x,pointer_y,WindowID,subw);
540
+ break;
541
+ }
542
+ }
543
+ break;
544
+
545
+ }
546
+ return 1;
547
+ }
548
+
549
+
550
+ /*
551
+ * Ruby stuff
552
+ */
553
+
554
+ VALUE cXevent;
555
+
556
+ /*
557
+ void xevent_rb_new(VALUE class) {
558
+ xevent_init();
559
+ }
560
+ */
561
+
562
+ VALUE xevent_rb_do(VALUE self, VALUE cmd) {
563
+ xevent_init();
564
+ xevent(RSTRING(cmd)->ptr);
565
+ return self;
566
+ }
567
+
568
+ void Init_xevent() {
569
+ cXevent = rb_define_class("Xevent", rb_cObject);
570
+ //rb_define_singleton_method(cXevent, "new", xevent_rb_new, 0);
571
+ rb_define_method(cXevent, "do", xevent_rb_do, 1);
572
+ }
573
+
574
+