xdo 0.0.1-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ #Encoding: UTF-8
2
+ #This file is part of Xdo.
3
+ #Copyright © 2009 Marvin Gülker
4
+ # Initia in potestate nostra sunt, de eventu fortuna iudicat.
5
+ require "rake/gempackagetask"
6
+ require "rake/rdoctask"
7
+ require "rake/testtask"
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = "xdo"
11
+ s.summary = "Simulate keyboard and mouse input via a ruby interface to xdotool and other console programs."
12
+ s.description =<<DESCRIPTION
13
+ XDo is a library to automate your mouse, fake keyboard input and
14
+ manipulate windows in a Linux X server environment. It's wrapped
15
+ around a lot of command line tools (see requirements) of which xdotool
16
+ is the main one, the others are usually installed.
17
+ DESCRIPTION
18
+ s.add_dependency("test-unit", ">= 2.0")
19
+ s.requirements = ["The xdotool command-line tool.", "xwininfo (usually installed)", "The xsel command-line tool.", "eject (usually installed)", "xkill (usually installed)"]
20
+ s.requirements << "The unit-test gem (will be installed if you don't have it)"
21
+ s.version = "0.0.1"
22
+ s.author = "Marvin Gülker"
23
+ s.email = "sutniuq@gmx.net"
24
+ s.platform = Gem::Platform::CURRENT
25
+ s.required_ruby_version = ">=1.9"
26
+ s.files = ["bin/xinfo.rb", Dir["lib/**/*.rb"], Dir["test/*.rb"], Dir["samples/*.rb"], "Rakefile", "lib/README.rdoc"].flatten
27
+ s.executables = ["xinfo.rb"]
28
+ s.has_rdoc = true
29
+ s.test_files = Dir["test/test_*.rb"]
30
+ s.rubyforge_project = "Automations"
31
+ end
32
+ Rake::GemPackageTask.new(spec).define
33
+
34
+ Rake::RDocTask.new do |rd|
35
+ rd.rdoc_files.include("lib/**/*.rb", "lib/README.rdoc")
36
+ rd.title = "xdo RDocs"
37
+ rd.main = "lib/README.rdoc"
38
+ end
39
+
40
+ Rake::TestTask.new("test") do |t|
41
+ t.pattern = "test/test_*.rb"
42
+ t.warning = true
43
+ end
44
+
45
+ desc "Tests XDo and then builds the gem file."
46
+ task :full_gem => [:test, :gem]
data/bin/xinfo.rb ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+ #Encoding: UTF-8
3
+ #This file is part of Xdo.
4
+ #Copyright © 2009 Marvin Gülker
5
+ # Initia in potestate nostra sunt, de eventu fortuna iudicat.
6
+ #
7
+ #This program displays information about the currently selected window
8
+ #and the mouse. The displayed infos are updated every 1/2 second,
9
+ #but set XInfo::UPDATE_TIME to another value if you'd like to change that.
10
+ require_relative("../lib/xdo/xwindow")
11
+ require_relative("../lib/xdo/mouse")
12
+ require "wx"
13
+ require_relative("../lib/xdo/wxaliases")
14
+
15
+ puts "=" * 80
16
+ puts "Started: #{Time.now}"
17
+ at_exit{puts "Finished: #{Time.now}"}
18
+
19
+
20
+ #--
21
+ #=================================================
22
+ #Backend
23
+ #=================================================
24
+ #++
25
+
26
+ #Class that retrieves the information of windows.
27
+ class InfoGetter
28
+
29
+ attr_reader :act_win
30
+ attr_reader :cursorpos
31
+
32
+ def initialize
33
+ @act_win = XDo::XWindow.from_active
34
+ @cursorpos = XDo::Mouse.position
35
+ end
36
+
37
+ def update
38
+ @act_win = XDo::XWindow.from_active
39
+ @cursorpos = XDo::Mouse.position
40
+ end
41
+
42
+ end
43
+
44
+ #--
45
+ #=================================================
46
+ #Frontend
47
+ #=================================================
48
+ #++
49
+ include Wx
50
+
51
+ #Frontend of this program.
52
+ class XInfo < App
53
+
54
+ #Time intervall of updating the infos, in milliseconds.
55
+ #Default is 500, which is 1/2 second.
56
+ UPDATE_TIME = 500
57
+
58
+ def on_init
59
+ puts "Creating main window"
60
+ @mainwindow = Frame.new(nil, -1, "XInfo", DEFAULT_POSITION, Size.new(300, 400), DEFAULT_FRAME_STYLE | STAY_ON_TOP)
61
+ @mainwindow.background_colour = NULL_COLOUR
62
+ puts "Creating controls"
63
+ create_controls
64
+ puts "Setting up timer"
65
+ create_updater
66
+
67
+ puts "Display GUI"
68
+ @mainwindow.show
69
+ end
70
+
71
+ def create_controls
72
+ StaticText.new(@mainwindow, -1, "Title of active window: ", Point.new(20, 20))
73
+ @title = TextCtrl.new(@mainwindow, -1, "", Point.new(20, 50), Size.new(260, 24), TE_READONLY)
74
+ StaticText.new(@mainwindow, -1, "ID of active window: ", Point.new(20, 80))
75
+ @id = TextCtrl.new(@mainwindow, -1, "", Point.new(20, 110), Size.new(260, 24), TE_READONLY)
76
+ StaticText.new(@mainwindow, -1, "Absoloute and relative upper-left coords: ", Point.new(20,140))
77
+ StaticText.new(@mainwindow, -1, "Abs: ", Point.new(20, 173))
78
+ @abs_xy = TextCtrl.new(@mainwindow, -1, "", Point.new(60, 170), Size.new(70, 24), TE_READONLY)
79
+ StaticText.new(@mainwindow, -1, "Rel: ", Point.new(150, 173))
80
+ @rel_xy = TextCtrl.new(@mainwindow, -1, "", Point.new(190, 170), Size.new(70, 24), TE_READONLY)
81
+ StaticText.new(@mainwindow, -1, "Size: ", Point.new(20, 200))
82
+ StaticText.new(@mainwindow, -1, "Width: ", Point.new(20, 233))
83
+ @width = TextCtrl.new(@mainwindow, -1, "", Point.new(65, 230), Size.new(70, 24), TE_READONLY)
84
+ StaticText.new(@mainwindow, -1, "Height: ", Point.new(150, 233))
85
+ @height = TextCtrl.new(@mainwindow, -1, "", Point.new(200, 230), Size.new(70, 24), TE_READONLY)
86
+
87
+ StaticText.new(@mainwindow, -1, "Mouse position: ", Point.new(20, 300))
88
+ StaticText.new(@mainwindow, -1, "X: ", Point.new(20, 333))
89
+ @x = TextCtrl.new(@mainwindow, -1, "", Point.new(60, 330), Size.new(70, 24), TE_READONLY)
90
+ StaticText.new(@mainwindow, -1, "Y: ", Point.new(150, 333))
91
+ @y = TextCtrl.new(@mainwindow, -1, "", Point.new(190, 330), Size.new(70, 24), TE_READONLY)
92
+
93
+ end
94
+
95
+ def create_updater
96
+ @updater = InfoGetter.new
97
+ Timer.every(UPDATE_TIME) do
98
+ begin
99
+ @updater.update
100
+ @title.text = @updater.act_win.title
101
+ @id.text = @updater.act_win.id.inspect
102
+ @abs_xy.text = @updater.act_win.abs_position.join(", ")
103
+ @rel_xy.text = @updater.act_win.rel_position.join(", ")
104
+ ary = @updater.act_win.size
105
+ @width.text = ary[0].inspect
106
+ @height.text = ary[1].inspect
107
+ rescue NoMethodError
108
+ puts "Window closed. Skipping NoMethodError. "
109
+ #Das aktive Fenster wird wohl gerade gelöscht.
110
+ #Daher nichts machen.
111
+ end
112
+
113
+ curpos = @updater.cursorpos
114
+ @x.text = curpos[0].inspect
115
+ @y.text = curpos[1].inspect
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+
123
+ begin
124
+ puts "Creating GUI"
125
+ x = XInfo.new
126
+ puts "Starting main loop"
127
+ x.main_loop
128
+ rescue
129
+ message = "An #{$!.class} occured. Backtrace: \n\n#{$@.join("\n")}"
130
+ message << "\n\nThe error message will be printed in the ~/.xinfo.rb.log file. "
131
+ message << "If you want to contact me about the error, send an email to sutniuq ät gmx Dot net and "
132
+ message << "attach the Err.log file."
133
+ msgbox = Wx::MessageDialog.new(nil, message, $!.class.to_s, OK | ICON_ERROR)
134
+ msgbox.show_modal
135
+ raise #for logging
136
+ end
data/lib/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ --
2
+ This file is part of Xdo.
3
+ Copyright © 2009 Marvin Gülker
4
+ Initia in potestate nostra sunt, de eventu fortuna iudicat.
5
+ ++
6
+ =XDo
7
+ XDo is a library to simmulate keyboard and mouse input and manipulating windows on the X server.
8
+ It's wrapped around the command-line tools xdotool[http://www.semicomplete.com/projects/xdotool/],
9
+ xsel[http://linux.die.net/man/1/xsel], xwininfo[http://linux.die.net/man/1/xwininfo], ecject[http://linux.die.net/man/1/eject] and xkill[http://linux.die.net/man/1/xkill],
10
+ so you will need to have them installed if you want to use Xdo (even if xsel, xwininfo, eject and xkill are usually already installed).
11
+ If not, as an Ubuntu or Debian user try to install them via
12
+ sudo apt-get install xdotool xsel xwininfo eject xkill
13
+ After they're installed, install XDo via RubyGems:
14
+ sudo gem install xdo
15
+ If you want to run the tests, change to the gem's installation directory and type "rake test".
16
+ Keep in mind that, while the tests run, you won't be able to use your computer, since they take control
17
+ of all things XDo is able to.
18
+ ==Usage
19
+ #Require some of XDo's files
20
+ require "xdo/keyboard"
21
+ require "xdo/mouse"
22
+ require "xdo/xwindow"
23
+ #Move the cursor
24
+ XDo::Mouse.move(100, 100)
25
+ #Simulate text (with special escape sequences!)
26
+ XDo::Keyboard.simulate("This is{TAB}text.")
27
+ #And this will move a window containing the string "gedit",
28
+ #unless it's maximized.
29
+ win = XDo::XWindow.from_name("gedit")
30
+ win.move(200, 200)
31
+ ==Files
32
+ You can require the following files in your projects:
33
+ * xdo/clipboard: Clipboard access
34
+ * xdo/drive: Get control of CD/DVD devices
35
+ * xdo/keyboard: Pretty self-explaining
36
+ * xdo/mouse: Automate the mouse
37
+ * xdo/xwindow: Manipulate windows in various ways
38
+ As an helpful extra, I created an executable ruby file "xinfo.rb". Thanks to RubyGems,
39
+ you can start this GUI tool right from the command line by typing:
40
+ xinfo.rb
41
+ It's by far not perfect, maybe not even good, but I think it can be useful sometimes
42
+ (you will need to have wxRuby installed, try <tt>sudo gem install wxruby-ruby19</tt>).
43
+ If you're looking for a more professional program, try the "X window information" tool.
44
+ ==Notes
45
+ * +xdotool+ rejects to accept the --window option although it's documented, so you can't use the +w_id+ parameter of many methods in XDo::Keyboard.
46
+ * I recommand the "X window information" tool to get infos about your windows if you aren't satisfied by the xinfo.rb shipped with this package.
47
+ ==Fairly incomplete
48
+ * I'm sure there are several things I didn't notice that can be automated somehow. If you know about, email me! Please add a description of the possibilities and a sample script (but don't expect that I will understand it - I only speak Ruby fluently, a bit C and a bit sh ;-) )
49
+ * Another interesting thing are the samples. There are many Linux distrubitions out there, and even many of them rely on X. I cannot test with another than a recent Ubuntu machine, but if you want to contribute and send samples for another OS, I want to encourage you to - I surely won't reject your work. :-)
50
+ ==License/Copyright
51
+ Copyright © 2009 Marvin Gülker
52
+ This library is free software; you may redistribute it and/or modify it
53
+ under the terms of Ruby's license (see http://www.ruby-lang.org/en/LICENSE.txt).
54
+ You can contact me at sutniuq ät gmx Dot net.
55
+ Initia in potestate nostra sunt, de eventu fortuna iudicat.
data/lib/xdo.rb ADDED
@@ -0,0 +1,28 @@
1
+ #Encoding: UTF-8
2
+ #This file is part of Xdo.
3
+ #Copyright © 2009 Marvin Gülker
4
+ # Initia in potestate nostra sunt, de eventu fortuna iudicat.
5
+
6
+ #The namespace of this library.
7
+ module XDo
8
+
9
+ #The command to start xdotool.
10
+ XDOTOOL = "xdotool"
11
+
12
+ #The command to start xsel.
13
+ XSEL = "xsel"
14
+
15
+ #The command to start xwininfo.
16
+ XWININFO = "xwininfo"
17
+
18
+ #The command to start xkill.
19
+ XKILL = "xkill"
20
+
21
+ #The command to start eject.
22
+ EJECT = "eject"
23
+
24
+ #Class for errors in this library.
25
+ class XError < StandardError
26
+ end
27
+
28
+ end #module XDo
@@ -0,0 +1,109 @@
1
+ #Encoding: UTF-8
2
+ require_relative("../xdo")
3
+
4
+ module XDo
5
+
6
+ #A module for interaction with the X clipboard. Please note, that the X clipboard
7
+ #consists of three parts: The PRIMARY clipboard, the CLIPBOARD clipboard, and
8
+ #the SECONDARY clipboard. The clipboard you access normally via [CTRL]+[C]
9
+ #or by right-clicking and selecting "copy", is usually the CLIPBOARD clipboard (but that
10
+ #depends on the application you use). The three main methods of this module (#read, #write
11
+ #and #clear) take a hash with the symbols of the clipboards to interact with. If you don't want to
12
+ #pass in the symbols, use the predefined read_xy, write_xy and clear_xy methods. They cannot
13
+ #access more than one clipboard at a time.
14
+ #The symbols for the clipboards are:
15
+ #[PRIMARY] :primary
16
+ #[SECONDARY] :secondary
17
+ #[CLIPBOARD] :clipboard
18
+ module Clipboard
19
+
20
+ class << self
21
+
22
+ ##
23
+ # :singleton-method: read_primary
24
+
25
+ ##
26
+ # :singleton-method: read_clipboard
27
+
28
+ ##
29
+ # :singleton-method: read_secondary
30
+
31
+ ##
32
+ # :singleton-method: write_primary
33
+
34
+ ##
35
+ # :singleton-method: write_clipboard
36
+
37
+ ##
38
+ # :singleton-method: write_secondary
39
+
40
+ ##
41
+ # :singleton-method: clear_primary
42
+
43
+ ##
44
+ # :singleton-method: clear_clipboard
45
+
46
+ ##
47
+ # :singleton-method: clear_secondary
48
+
49
+ [:primary, :clipboard, :secondary].each do |sym|
50
+
51
+ define_method(:"read_#{sym}") do
52
+ read({sym => true})[sym]
53
+ end
54
+
55
+ define_method(:"write_#{sym}") do |text|
56
+ write(text, {sym => true})
57
+ text
58
+ end
59
+
60
+ define_method(:"clear_#{sym}") do
61
+ clear({sym => true})
62
+ nil
63
+ end
64
+
65
+ end
66
+
67
+ #Reads text from the X clipboard. The +from+ argument specifies
68
+ #from what clipboard you want to read (in 70% of all cases you
69
+ #want to read from :clipboard). Return value is a hash with the
70
+ #clipboards you specified as the keys. The contents of the clipboards
71
+ #are the values. You can also use one of the read_xy methods directly.
72
+ def read(from = {:clipboard => true})
73
+ hsh = {}
74
+ hsh[:primary] = `#{XSEL}` if from[:primary]
75
+ hsh[:clipboard] = `#{XSEL} -b` if from[:clipboard]
76
+ hsh[:secondary] = `#{XSEL} -s` if from[:secondary]
77
+ hsh
78
+ end
79
+
80
+ #Writes data to the X clipboard. The +to+ argument soecifies
81
+ #the clipboard you want to write to. If you want to be able to paste
82
+ #your text via [CTRL]+[v], use :clipboard. You can also use the
83
+ #write_xy methods if you don't want to pass in the hash.
84
+ def write(text, to = {:primary => true, :clipboard => true})
85
+ IO.popen("xsel -i", "w"){|io| io.write(text)} if to[:primary]
86
+ IO.popen("xsel -b -i", "w"){|io| io.write(text)} if to[:clipboard]
87
+ IO.popen("xsel -s -i", "w"){|io| io.write(text)} if to[:secondary]
88
+ text
89
+ end
90
+
91
+ #Append data to text already written to the X clipboard. As in #write,
92
+ #you can specify the clipboard you want to append text to.
93
+ def append(text, to = {:primary => true, :clipboard => true})
94
+ IO.popen("xsel -a -i", "w"){|io| io.write(text)} if to[:primary]
95
+ IO.popen("xsel -b -a -i", "w"){|io| io.write(text)} if to[:clipboard]
96
+ IO.popen("xsel -s -a -i", "w"){|io| io.write(text)} if to[:secondary]
97
+ end
98
+
99
+ #Clears the specified clipboards.
100
+ def clear(clips = {:primary => true, :clipboard => true})
101
+ `#{XSEL} -c` if clips[:primary]
102
+ `#{XSEL} -b -c` if clips[:clipboard]
103
+ `#{XSEL} -s -c` if clips[:secondary]
104
+ nil
105
+ end
106
+
107
+ end
108
+ end
109
+ end
data/lib/xdo/drive.rb ADDED
@@ -0,0 +1,66 @@
1
+ #Encoding: UTF-8
2
+ require "open3"
3
+ require_relative("../xdo")
4
+
5
+ module XDo
6
+
7
+ #Some methods to interact with CD (and DVD, of course) drives.
8
+ #The value of the +drive+ parameter of many methods can be
9
+ #either a mount point or a device file like scd0.
10
+ #
11
+ #If you don't pass in a drive name, the returnvalue of #default will
12
+ #be used.
13
+ module Drive
14
+
15
+ class << self
16
+ include Open3
17
+ #Opens a drive.
18
+ def eject(drive = nil)
19
+ err = ""
20
+ drive = default unless drive
21
+ popen3("#{XDo::EJECT} #{drive}"){|stdin, stdout, stderr| err << stderr.read}
22
+ raise(XDo::XError, err) unless err.empty?
23
+ true
24
+ end
25
+
26
+ #Closes a drive.
27
+ def close(drive = nil)
28
+ drive = default unless drive
29
+ err = ""
30
+ popen3("eject -t #{drive}"){|stdin, stdout, stderr| err << stderr.read}
31
+ raise(XDo::XError, err) unless err.empty?
32
+ end
33
+
34
+ #Returns the mount point of the default drive.
35
+ #You can use it as a value for a +drive+ parameter.
36
+ def default
37
+ err = ""
38
+ out = ""
39
+ popen3("#{XDo::EJECT} -d"){|stdin, stdout, stderr| out << stdout.read; err << stderr.read}
40
+ raise(XDo::XError, err) unless err.empty?
41
+ out.match(/`(.*)'/)[1]
42
+ end
43
+
44
+ #Locks a drive, so that it can't be opened by
45
+ #using the eject button.
46
+ def lock(drive = nil)
47
+ drive = default unless drive
48
+ err = ""
49
+ popen3("#{XDo::EJECT} -i on #{drive}"){|stdin, stdout, stderr| err << stderr.read}
50
+ raise(XDo::XError, err) unless err.empty?
51
+ true
52
+ end
53
+
54
+ #Unlocks a drive, so that it can be opened
55
+ #by the eject button.
56
+ def release(drive = nil)
57
+ drive = default unless drive
58
+ err = ""
59
+ popen3("#{XDo::EJECT} -i off #{drive}")
60
+ raise(XDo::XError,err) unless err.empty?
61
+ true
62
+ end
63
+
64
+ end
65
+ end
66
+ end