swm 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/CHANGELOG.md +3 -0
- data/Guardfile +6 -0
- data/README.md +41 -1
- data/bin/swm +57 -1
- data/lib/swm.rb +5 -4
- data/lib/swm/command_runner.rb +13 -0
- data/lib/swm/commands/move_command.rb +51 -0
- data/lib/swm/screen.rb +7 -0
- data/lib/swm/version.rb +1 -1
- data/lib/swm/window.rb +72 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/window_spec.rb +26 -0
- data/swm.gemspec +4 -0
- metadata +56 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b9b935a723ff0b91c3e27f18b2d54153d691b57
|
4
|
+
data.tar.gz: 101329a7748b14884ffd2a1dbc6a821a2f272eff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f425c6c926ff11f6a083d291df1b374573eb14343de122372b5f978db72769ed7d60b083e59c9f43a42868d21b5b9066db15b0f6917d292e01e52fe7cd015915
|
7
|
+
data.tar.gz: 85471aa02e014ae4fa1f5d8e6fdfdc1d04d1e6174558daeca1761caf0280da215012f693eafda7b464639873cbcb575c65808f51b27a752350bea4f50b5ef151
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -8,9 +8,49 @@ SWM is a utility to place and resize windows, written for Ubuntu. It might work
|
|
8
8
|
|
9
9
|
$ gem install swm
|
10
10
|
|
11
|
+
## Dependencies
|
12
|
+
|
13
|
+
Some command line tools are needed:
|
14
|
+
|
15
|
+
- xdotool (for getting window id if current window)
|
16
|
+
- wmctrl (for moving and reizing windows)
|
17
|
+
- xdpyinfo (for getting screen dimensions)
|
18
|
+
- xwininfo (for getting window information)
|
19
|
+
|
20
|
+
Install these with apt-get if they are not on your system.
|
21
|
+
|
11
22
|
## Usage
|
12
23
|
|
13
|
-
|
24
|
+
### Moving windows
|
25
|
+
|
26
|
+
Move windows with the move subcommand.
|
27
|
+
It accepts parameters x and y which can both be specified in percentages of free screen space.
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
|
31
|
+
swm move --x 50% --y 50%
|
32
|
+
|
33
|
+
Will center the window
|
34
|
+
|
35
|
+
swm move --x 0%
|
36
|
+
|
37
|
+
Will move the window to the left edge of the sceen, preserving the Y position
|
38
|
+
|
39
|
+
There are some predefined constants that can be used to specify position:
|
40
|
+
|
41
|
+
- For X these are: left, middle and right.
|
42
|
+
- For Y is is: top, middle, bottom
|
43
|
+
|
44
|
+
For example:
|
45
|
+
|
46
|
+
swm move --x right --y middle
|
47
|
+
|
48
|
+
Will move the window to the middle of the right edge.
|
49
|
+
|
50
|
+
|
51
|
+
### Resizing windows
|
52
|
+
|
53
|
+
Not yet supported
|
14
54
|
|
15
55
|
## Contributing
|
16
56
|
|
data/bin/swm
CHANGED
@@ -1,5 +1,61 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
lib = File.expand_path('../../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'trollop'
|
3
7
|
require 'swm'
|
4
8
|
|
5
|
-
|
9
|
+
def run
|
10
|
+
options = get_options
|
11
|
+
begin
|
12
|
+
Swm::CommandRunner.run options[:command], options[:command_options], options[:global_options]
|
13
|
+
rescue Exception => ex
|
14
|
+
puts ex.message
|
15
|
+
exit(1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_options
|
20
|
+
global_options = Trollop::options do
|
21
|
+
banner "utility that can move and resize windows"
|
22
|
+
stop_on %w[ move resize ]
|
23
|
+
end
|
24
|
+
{ global_options: global_options }.merge get_command
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_command
|
28
|
+
command = ARGV.shift
|
29
|
+
Trollop.die "no command" unless command
|
30
|
+
command = command.to_sym
|
31
|
+
{ command: command }.merge get_command_options(command)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_command_options(command)
|
35
|
+
{
|
36
|
+
command_options: case command
|
37
|
+
when :move
|
38
|
+
get_move_options
|
39
|
+
when :resize
|
40
|
+
get_resize_options
|
41
|
+
else
|
42
|
+
Trollop::die "unknown command #{command.to_s}"
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_move_options
|
48
|
+
Trollop::options do
|
49
|
+
opt :x, "The placement on the x-axis: left, middle, right, or 0%-100%", type: String
|
50
|
+
opt :y, "The placement on the y-axis: top, middle, bottom, or 0%-100%", type: String
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_resize_options
|
55
|
+
Trollop::options do
|
56
|
+
opt :width, "The width in pixels", type: Integer
|
57
|
+
opt :height, "The height in pixels", type: Integer
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
run
|
data/lib/swm.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require_relative "swm/version"
|
2
|
+
require_relative "swm/window"
|
3
|
+
require_relative "swm/screen"
|
4
|
+
require_relative "swm/command_runner"
|
5
|
+
require_relative "swm/commands/move_command"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Swm
|
2
|
+
|
3
|
+
class CommandRunner
|
4
|
+
def self.run(command, command_options = {}, global_options = {})
|
5
|
+
command = get_command_class(command).new command_options, global_options
|
6
|
+
command.run
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.get_command_class(command)
|
10
|
+
Swm.const_get "#{command.capitalize}Command"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Swm
|
2
|
+
class MoveCommand
|
3
|
+
def initialize(command_options = {}, global_options = {})
|
4
|
+
@command_options = command_options
|
5
|
+
@global_options = global_options
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
window = Swm::Window.current
|
10
|
+
|
11
|
+
x_percentage = get_x_percentage
|
12
|
+
y_percentage = get_y_percentage
|
13
|
+
|
14
|
+
screen_dimensions = Screen.dimensions
|
15
|
+
|
16
|
+
x = y = nil
|
17
|
+
x = ((screen_dimensions[0] - window.width) * x_percentage / 100.0).to_i if x_percentage
|
18
|
+
y = ((screen_dimensions[1] - window.height) * y_percentage / 100.0).to_i if y_percentage
|
19
|
+
|
20
|
+
window.move x, y
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_x_percentage
|
24
|
+
get_placement_percentage :x, {
|
25
|
+
left: 0,
|
26
|
+
middle: 50,
|
27
|
+
right: 100
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_y_percentage
|
32
|
+
get_placement_percentage :y, {
|
33
|
+
top: 0,
|
34
|
+
middle: 50,
|
35
|
+
bottom: 100
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_placement_percentage(axis, constants)
|
40
|
+
raw_value = @command_options[axis]
|
41
|
+
return nil if raw_value.nil?
|
42
|
+
if value = constants[raw_value.to_sym]
|
43
|
+
value
|
44
|
+
elsif /(\d+(\.\d+)?)\%/ =~ raw_value
|
45
|
+
$1.to_f
|
46
|
+
else
|
47
|
+
raise "Unknown placement option: #{raw_value}. Valid options are percentages (e.g. 30%) and [#{constants.map{|x| x.first.to_s}.join(' ')}]"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/swm/screen.rb
ADDED
data/lib/swm/version.rb
CHANGED
data/lib/swm/window.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Swm
|
2
|
+
class Window
|
3
|
+
def self.current
|
4
|
+
Window.new `xdotool getwindowfocus`.to_i
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(id)
|
8
|
+
@id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def width
|
12
|
+
xwininfo_integer_property "Width"
|
13
|
+
end
|
14
|
+
|
15
|
+
def height
|
16
|
+
xwininfo_integer_property "Height"
|
17
|
+
end
|
18
|
+
|
19
|
+
def pos_x
|
20
|
+
xwininfo_integer_property "Absolute upper-left X"
|
21
|
+
end
|
22
|
+
|
23
|
+
def pos_y
|
24
|
+
xwininfo_integer_property "Absolute upper-left Y"
|
25
|
+
end
|
26
|
+
|
27
|
+
def move(x, y)
|
28
|
+
x ||= pos_x
|
29
|
+
y ||= pos_y
|
30
|
+
command = "wmctrl -i -r #{@id} -e 0,#{x},#{y},#{width},#{height}"
|
31
|
+
exec command
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
##
|
37
|
+
# xwininfo will tell stuff about the requested window
|
38
|
+
#
|
39
|
+
# Sample output:
|
40
|
+
#
|
41
|
+
# xwininfo: Window id: 0x3c00862 "xwininfo -id 62916706"
|
42
|
+
#
|
43
|
+
# Absolute upper-left X: 1
|
44
|
+
# Absolute upper-left Y: 52
|
45
|
+
# Relative upper-left X: 0
|
46
|
+
# Relative upper-left Y: 0
|
47
|
+
# Width: 992
|
48
|
+
# Height: 596
|
49
|
+
# Depth: 32
|
50
|
+
# Visual: 0x6c
|
51
|
+
# Visual Class: TrueColor
|
52
|
+
# Border width: 0
|
53
|
+
# Class: InputOutput
|
54
|
+
# Colormap: 0x3c00005 (not installed)
|
55
|
+
# Bit Gravity State: NorthWestGravity
|
56
|
+
# Window Gravity State: NorthWestGravity
|
57
|
+
# Backing Store State: NotUseful
|
58
|
+
# Save Under State: no
|
59
|
+
# Map State: IsViewable
|
60
|
+
# Override Redirect State: no
|
61
|
+
# Corners: +1+52 -927+52 -927-432 +1-432
|
62
|
+
# -geometry 110x33+-7+24
|
63
|
+
#
|
64
|
+
def xwininfo
|
65
|
+
@xwininfo ||= `xwininfo -id #{@id}`
|
66
|
+
end
|
67
|
+
|
68
|
+
def xwininfo_integer_property(name)
|
69
|
+
/#{name}: +(\d+)/.match(xwininfo)[1].to_i
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'swm'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
21
|
+
RSpec.configure do |config|
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Swm::Window do
|
4
|
+
|
5
|
+
let(:window) { Swm::Window.current }
|
6
|
+
|
7
|
+
describe 'height' do
|
8
|
+
subject { window.height }
|
9
|
+
it { should be_kind_of Integer }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'width' do
|
13
|
+
subject { window.width }
|
14
|
+
it { should be_kind_of Integer }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'pos_x' do
|
18
|
+
subject { window.pos_x }
|
19
|
+
it { should be_kind_of Integer }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'pos_y' do
|
23
|
+
subject { window.pos_y }
|
24
|
+
it { should be_kind_of Integer }
|
25
|
+
end
|
26
|
+
end
|
data/swm.gemspec
CHANGED
@@ -24,6 +24,10 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
25
|
spec.require_paths = ["lib"]
|
26
26
|
|
27
|
+
spec.add_dependency "trollop"
|
28
|
+
|
27
29
|
spec.add_development_dependency "bundler", "~> 1.3"
|
28
30
|
spec.add_development_dependency "rake"
|
31
|
+
spec.add_development_dependency "rspec"
|
32
|
+
spec.add_development_dependency "guard-rspec"
|
29
33
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lasse Skindstad Ebert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: trollop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,34 @@ dependencies:
|
|
38
52
|
- - '>='
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
41
83
|
description: "\n Simple Window Manager is a utillity to move and place windows
|
42
84
|
in Ubuntu.\n It might work with other *nix distributions.\n\n The utillity
|
43
85
|
is intended to be used with keyboard shortcuts, and is\n always operating on
|
@@ -50,13 +92,22 @@ extensions: []
|
|
50
92
|
extra_rdoc_files: []
|
51
93
|
files:
|
52
94
|
- .gitignore
|
95
|
+
- .rspec
|
96
|
+
- CHANGELOG.md
|
53
97
|
- Gemfile
|
98
|
+
- Guardfile
|
54
99
|
- LICENSE.txt
|
55
100
|
- README.md
|
56
101
|
- Rakefile
|
57
102
|
- bin/swm
|
58
103
|
- lib/swm.rb
|
104
|
+
- lib/swm/command_runner.rb
|
105
|
+
- lib/swm/commands/move_command.rb
|
106
|
+
- lib/swm/screen.rb
|
59
107
|
- lib/swm/version.rb
|
108
|
+
- lib/swm/window.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
- spec/unit/window_spec.rb
|
60
111
|
- swm.gemspec
|
61
112
|
homepage: https://github.com/lasseebert/swm
|
62
113
|
licenses:
|
@@ -82,4 +133,6 @@ rubygems_version: 2.0.2
|
|
82
133
|
signing_key:
|
83
134
|
specification_version: 4
|
84
135
|
summary: Simple Window Manager for Ubuntu
|
85
|
-
test_files:
|
136
|
+
test_files:
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
- spec/unit/window_spec.rb
|