rlirc 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+