windows 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ TODO
20
+ samples/development.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in windows.gemspec
4
+ gemspec
@@ -0,0 +1,64 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ windows (0.0.1)
5
+ ruby-wmctrl
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.0.7)
11
+ diff-lcs (1.1.3)
12
+ ffi (1.0.11)
13
+ fuubar (1.0.0)
14
+ rspec (~> 2.0)
15
+ rspec-instafail (~> 0.2.0)
16
+ ruby-progressbar (~> 0.0.10)
17
+ guard (1.3.2)
18
+ listen (>= 0.4.2)
19
+ thor (>= 0.14.6)
20
+ guard-rspec (1.2.1)
21
+ guard (>= 1.1)
22
+ libnotify (0.7.2)
23
+ ffi (~> 1.0.0)
24
+ listen (0.5.0)
25
+ method_source (0.8)
26
+ multi_json (1.3.6)
27
+ pkg-config (1.1.4)
28
+ pry (0.9.10)
29
+ coderay (~> 1.0.5)
30
+ method_source (~> 0.8)
31
+ slop (~> 3.3.1)
32
+ rb-inotify (0.8.8)
33
+ ffi (>= 0.5.0)
34
+ rspec (2.11.0)
35
+ rspec-core (~> 2.11.0)
36
+ rspec-expectations (~> 2.11.0)
37
+ rspec-mocks (~> 2.11.0)
38
+ rspec-core (2.11.1)
39
+ rspec-expectations (2.11.3)
40
+ diff-lcs (~> 1.1.3)
41
+ rspec-instafail (0.2.4)
42
+ rspec-mocks (2.11.2)
43
+ ruby-progressbar (0.0.10)
44
+ ruby-wmctrl (0.0.4)
45
+ pkg-config
46
+ simplecov (0.6.4)
47
+ multi_json (~> 1.0)
48
+ simplecov-html (~> 0.5.3)
49
+ simplecov-html (0.5.3)
50
+ slop (3.3.3)
51
+ thor (0.16.0)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ fuubar
58
+ guard-rspec
59
+ libnotify
60
+ pry
61
+ rb-inotify (~> 0.8.8)
62
+ rspec
63
+ simplecov
64
+ windows!
@@ -0,0 +1,11 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', version: 2, cli: '--color --format Fuubar' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch(%r{^lib/windows/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+ watch('lib/windows.rb') { "spec" }
10
+ end
11
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 lefty313
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ windows
2
+ ====
3
+
4
+ Ruby framework for manipulating Xwindow windows
5
+
6
+ ### Installation for unix system
7
+ ```bash
8
+ sudo apt-get install libx11-dev libglib2.0-dev libxmu-dev
9
+ ```
10
+ ``` ruby
11
+ gem install windows
12
+ ```
13
+
14
+ ### Usage
15
+ ```ruby
16
+ require 'windows'
17
+
18
+ p = Windows::Project.new(:default,'~')
19
+
20
+ p.open_window('chromium-browser').move(:left)
21
+ p.open_window('sublime-text-2 .').move(:right)
22
+ p.open_window('gnome-terminal').move(:bottom_right).on_top
23
+
24
+ sleep 5
25
+ p.close
26
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ require "windows/version"
2
+ require "windows/project"
3
+ require "windows/engines/xwindow"
4
+
5
+ module Windows
6
+ Window = Engines::XWindow
7
+ ActiveWindowKey = :active
8
+ end
9
+
@@ -0,0 +1,5 @@
1
+ class Numeric
2
+ def percent(arg)
3
+ (self * arg / 100).floor
4
+ end
5
+ end
@@ -0,0 +1,68 @@
1
+ require 'wmctrl'
2
+ require 'windows/structures'
3
+
4
+ class WMCtrl
5
+ include Windows::Structures
6
+
7
+ def action(*args)
8
+ action_window(*args)
9
+ pause
10
+ end
11
+
12
+ def register_window(&block)
13
+ before = windows
14
+ block.call
15
+
16
+ # wait until windows list refresh
17
+ after = loop do
18
+ pause
19
+ after = windows
20
+ if after.ids != before.ids
21
+ break after - before
22
+ end
23
+ end
24
+ end
25
+
26
+ def desktops
27
+ list = list_desktops.map {|d| Desktop.new(d[:id], d[:workarea]) }
28
+ Collection.new(list)
29
+ end
30
+
31
+ def windows
32
+ list = list_windows(true).map do |w|
33
+ # wmctrl mark default desktop as -1
34
+ desktop_id = w[:desktop].abs
35
+ desktop = find_desktop(desktop_id)
36
+ Window.new(w[:id], w[:title], desktop, *w[:geometry], w[:active])
37
+ end.sort_by(&:id)
38
+ Collection.new(list)
39
+ end
40
+
41
+ def find_window(id)
42
+ windows.find{ |w| w.id == id }
43
+ end
44
+
45
+ def active_window
46
+ windows.find(&:active)
47
+ end
48
+
49
+ def find_desktop(id)
50
+ desktops.find {|d| d.id == id}
51
+ end
52
+
53
+ def spawn_window(command)
54
+ register_window do
55
+ pid = Process.spawn(command, :out => :close, :err => :close)
56
+ Process.detach(pid)
57
+ end
58
+ rescue Errno::ENOENT
59
+ raise "Failed to create window with command: #{command}. Maybe a typo?"
60
+ end
61
+
62
+ private
63
+
64
+ def pause
65
+ sleep 0.05
66
+ end
67
+
68
+ end
@@ -0,0 +1,82 @@
1
+ require 'forwardable'
2
+ require 'windows/engines/wmctrl'
3
+ require 'windows/units/unit_converter'
4
+
5
+ module Windows
6
+ module Engines
7
+ class XWindow
8
+ extend Forwardable
9
+
10
+ def_delegators :window, :title, :x, :y, :width, :height, :desktop
11
+
12
+ attr_reader :engine, :created_at, :id
13
+ attr_accessor :command
14
+
15
+ def initialize(command, options = {}, engine = nil)
16
+ @engine = engine || WMCtrl.new
17
+ @command = command
18
+ end
19
+
20
+ def move(*args)
21
+ args = convert_units(args)
22
+ undock
23
+ action(:move_resize, 0, *args)
24
+ end
25
+
26
+ def close
27
+ action(:close)
28
+ @id = false
29
+ @created_at = false
30
+ end
31
+
32
+ def focus
33
+ action(:activate)
34
+ end
35
+
36
+ def undock
37
+ action(:change_state, "remove", "maximized_vert", "maximized_horz")
38
+ end
39
+
40
+ def create
41
+ return false if created_at
42
+
43
+ window = engine.find_window(command)
44
+ window ||= engine.spawn_window(command)
45
+
46
+ @id = window.id
47
+ @created_at = Time.now
48
+ self
49
+ end
50
+
51
+ def window
52
+ create
53
+ engine.find_window(id)
54
+ end
55
+
56
+ def on_top
57
+ action(:change_state, "add", "above")
58
+ end
59
+
60
+ def not_on_top
61
+ action(:change_state, "remove", "above")
62
+ end
63
+
64
+ def action(*args)
65
+ create
66
+ engine.action(id, *args)
67
+ self
68
+ end
69
+
70
+ def maximize
71
+ action(:change_state, "add", "maximized_vert", "maximized_horz")
72
+ end
73
+
74
+ private
75
+
76
+ def convert_units(args)
77
+ converter = Units::UnitConverter.new(desktop, *args)
78
+ converter.convert
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,31 @@
1
+ require 'pathname'
2
+ require 'windows'
3
+
4
+ module Windows
5
+ class Project
6
+ attr_reader :root, :name, :windows
7
+
8
+ def initialize(name, path)
9
+ @windows = Array.new
10
+ @root = Pathname.new(path).expand_path
11
+ @name = name
12
+ end
13
+
14
+ def close
15
+ windows.each(&:close)
16
+ end
17
+
18
+ def open_window(command, opts = {}, &block)
19
+ window = Windows::Window.new(command, opts).create
20
+ yield window if block_given?
21
+ windows.push(window)
22
+ window
23
+ end
24
+
25
+ def default_terminal
26
+ open_window(Windows::ActiveWindowKey)
27
+ end
28
+
29
+ end
30
+ end
31
+
@@ -0,0 +1,7 @@
1
+ # load all files from structures dir
2
+ Dir[File.dirname(__FILE__) + '/structures/*.rb'].each {|file| require file }
3
+
4
+ module Windows
5
+ module Structures
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ require 'delegate'
2
+
3
+ module Windows
4
+ module Structures
5
+ class Collection < SimpleDelegator
6
+ def ids
7
+ collect(&:id)
8
+ end
9
+
10
+ def -(collection)
11
+ diff_id = ids - collection.ids
12
+ return nil if diff_id.empty?
13
+
14
+ raise "I don't know which item is correct #{diff_id}" if diff_id.count != 1
15
+ find { |r| r.id == diff_id[0] }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Windows
2
+ module Structures
3
+ class Desktop < Struct.new(:id, :geometry)
4
+ def width
5
+ geometry[2]
6
+ end
7
+
8
+ def height
9
+ geometry[3]
10
+ end
11
+
12
+ def x_offset
13
+ geometry[0]
14
+ end
15
+
16
+ def y_offset
17
+ geometry[1]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ module Windows
2
+ module Structures
3
+ class Geometry < Struct.new(:x, :y, :w, :h)
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Windows
2
+ module Structures
3
+ class Window < Struct.new(:id, :title, :desktop, :x, :y, :width, :height, :active)
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,64 @@
1
+ module Windows
2
+ module Units
3
+ module Converter
4
+ require 'windows/core_ext/numeric'
5
+
6
+ class Base
7
+ attr_reader :el, :options
8
+
9
+ def initialize(el, options = {})
10
+ @el = el
11
+ @options = options
12
+ end
13
+
14
+ def run
15
+ raise "you must implement this method"
16
+ end
17
+ end
18
+
19
+ module Formats
20
+ class Percent < Base
21
+ def run
22
+ raise "you must specify options[:base] to change number to percent" unless options[:base]
23
+ options[:base].percent(el)
24
+ end
25
+ end
26
+
27
+ class Pixel < Base
28
+ def run
29
+ el
30
+ end
31
+ end
32
+
33
+ SUPPORTED_FORMATS = {
34
+ :percent => Percent,
35
+ :pixel => Pixel
36
+ }
37
+
38
+ def supported_formats
39
+ SUPPORTED_FORMATS.keys
40
+ end
41
+
42
+ def format_for(format, *args)
43
+ klass = SUPPORTED_FORMATS[format]
44
+ raise "I only support this formats #{supported_formats}" unless klass
45
+ klass.new(*args)
46
+ end
47
+ end
48
+
49
+ class Finder < Struct.new(:el)
50
+ include Formats
51
+
52
+ def to(format, *args)
53
+ format_for(format, el, *args).run
54
+ end
55
+ end
56
+
57
+ def converter(el)
58
+ @unit_converter ||= Finder.new(el)
59
+ @unit_converter.el = el
60
+ @unit_converter
61
+ end
62
+ end
63
+ end
64
+ end