xdo 0.0.1-x86-linux

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/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