sapristi 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fd92d587999ee50bc8eda291f716e33e72e7c56301fb7e56a62a6a0c65bc4f0
4
- data.tar.gz: ff62aedea624f0e2738ba68ca81bc6303fd0fb048681df16e78209303a1f9fad
3
+ metadata.gz: a6f73d47dbbde92a37f2d64ccf7cebbadbe9fb3f078e097d4c08e0eb70dd306d
4
+ data.tar.gz: 28d8025def810ec571339fc7dada6ce05d7639120ecc3101870500400084b831
5
5
  SHA512:
6
- metadata.gz: c9804608416798a040e3ecb1316d238e44f52ac9e6a00c547ace71511982c26c089bbbdea65d6ae1ad337b819634f849239b7597ab5de0efb3c8d461415916e8
7
- data.tar.gz: 15e24fddd27bcc428470f42ef663dac3a1b9b2b711e122412a26ccd13c3b09445840445fe26123dba4dcbfa2ffd25b260851dedf338d3e069942e84071a4ab24
6
+ metadata.gz: 9dca2f730eb0bacdac26279773efe1226f5b658a4f3b6dc03cf6bc6fccdd6528b9fec69e8a5cad7c00692c241b3f721a9533a16b759cf679d6fafa63213fb098
7
+ data.tar.gz: 8eb2cf7358975e50a751867fd0ea98f84c25c7cebe90e3b45a8b62c93bd96a83ba763954af3a5087bfbf07d1088b387baa083edefd0be82b1d07b81d77db7ecd
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Sapristi
2
2
 
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/e168b7940a847148f617/maintainability)](https://codeclimate.com/github/sapristi-tool/sapristi/maintainability)
4
+
3
5
  Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sapristi`. To experiment with that code, run `bin/console` for an interactive prompt.
4
6
 
5
7
  TODO: Delete this and the text above, and describe your gem
@@ -15,6 +15,7 @@ require 'sapristi/adapters/linux/window_manager'
15
15
  require 'sapristi/adapters/linux/process_manager'
16
16
  require 'sapristi/new_process_window_detector'
17
17
  require 'sapristi/monitor'
18
+ require 'sapristi/adapters/os_factory'
18
19
  require 'logger'
19
20
 
20
21
  module Sapristi
@@ -3,7 +3,7 @@
3
3
  module Sapristi
4
4
  module Linux
5
5
  class ProcessManager
6
- def execute_and_detach(cmd)
6
+ def self.execute_and_detach(cmd)
7
7
  process_pid = begin
8
8
  Process.spawn(cmd)
9
9
  rescue StandardError
@@ -13,7 +13,7 @@ module Sapristi
13
13
  Process.detach process_pid
14
14
  end
15
15
 
16
- def kill(waiter)
16
+ def self.kill(waiter)
17
17
  Process.kill 'KILL', waiter.pid
18
18
  # sleep 1 # XLIB error for op code
19
19
  raise Error, 'Error executing process, it didn\'t open a window'
@@ -24,7 +24,7 @@ module Sapristi
24
24
  `ps -u #{user_id}`.split("\n")[1..nil].map(&:to_i)
25
25
  end
26
26
 
27
- def cmd_for_pid(pid)
27
+ def self.cmd_for_pid(pid)
28
28
  cmd = "ps -o cmd -p #{pid}"
29
29
  line = `#{cmd}`.split("\n")[1]
30
30
  raise Error, "No process found pid=#{pid}" unless line
@@ -36,16 +36,76 @@ module Sapristi
36
36
  GRAVITY = 0
37
37
  TIME_TO_APPLY_DIMENSIONS = 0.25
38
38
 
39
- def move_resize(window, geometry)
39
+ def move(window, x_position, y_position)
40
+ geometry = complete_geometry(window.id, x_position: x_position, y_position: y_position)
41
+ move_resize(window, geometry)
42
+ end
43
+
44
+ def resize(window, width, height)
45
+ geometry = complete_geometry(window.id, width: width, height: height)
46
+ move_resize(window, geometry)
47
+ end
48
+
49
+ def move_resize(window, requested)
40
50
  remove_extended_hints(window) if window.maximized_horizontally? || window.maximized_vertically?
51
+
52
+ geometry = requested.clone
53
+ left, right, top, bottom = window.frame_extents || [0, 0, 0, 0]
54
+ geometry[2] -= left + right
55
+ geometry[3] -= top + bottom
56
+
41
57
  @display.action_window(window.id, :move_resize, GRAVITY, *geometry)
42
58
  sleep TIME_TO_APPLY_DIMENSIONS
59
+ check_expected_geometry window, requested
43
60
  end
44
61
 
62
+ private
63
+
45
64
  EXTENDED_HINTS = %w[maximized_vert maximized_horz].freeze
46
65
 
47
66
  def remove_extended_hints(window)
48
67
  display.action_window(window.id, :change_state, 'remove', *EXTENDED_HINTS)
68
+ sleep TIME_TO_APPLY_DIMENSIONS
69
+ end
70
+
71
+ def complete_geometry(window_id, requested)
72
+ window = @display.windows(id: window_id).first
73
+ Geometry.new(window).merge(requested)
74
+ end
75
+
76
+ LABELS = %w[x y width heigth].freeze
77
+
78
+ def check_expected_geometry(window, expected)
79
+ actual_window = @display.windows(id: window.id).first
80
+ actual = actual_window.exterior_frame || actual_window.geometry
81
+
82
+ return if actual.eql? expected
83
+
84
+ # rubocop:disable Layout/LineLength
85
+ ::Sapristi.logger.warn "Geometry mismatch #{WindowManager.text_diff(actual, expected)}, requested=#{expected}, window=#{window.title}"
86
+ # rubocop:enable Layout/LineLength
87
+ end
88
+
89
+ def self.text_diff(actual, expected)
90
+ diffs = 4.times.filter { |index| !expected[index].eql? actual[index] }
91
+ diffs.map do |diff_index|
92
+ "#{LABELS[diff_index]}: expected=#{expected[diff_index]}, actual=#{actual[diff_index]}"
93
+ end.join(', ')
94
+ end
95
+ end
96
+
97
+ class Geometry
98
+ def initialize(window)
99
+ @geometry = window.exterior_frame || window.geometry
100
+ end
101
+
102
+ attr_reader :geometry
103
+
104
+ def merge(requested)
105
+ [requested.fetch(:x_position, geometry[0]),
106
+ requested.fetch(:y_position, geometry[1]),
107
+ requested.fetch(:width, geometry[2]),
108
+ requested.fetch(:height, geometry[3])]
49
109
  end
50
110
  end
51
111
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'os'
4
+
5
+ module Sapristi
6
+ class OSFactory
7
+ def initialize
8
+ @os = OS
9
+ end
10
+
11
+ def factory_module
12
+ return Linux if linux?
13
+
14
+ raise Error, "OS not implemented: #{os_name}"
15
+ end
16
+
17
+ def window_manager
18
+ factory_module.const_get('WindowManager').new
19
+ end
20
+
21
+ def monitor_manager
22
+ factory_module.const_get('MonitorManager').new
23
+ end
24
+
25
+ def process_manager
26
+ factory_module.const_get('ProcessManager')
27
+ end
28
+
29
+ def linux?
30
+ @os.linux?
31
+ end
32
+
33
+ def os_name
34
+ @os.parse_os_release[:pretty_name]
35
+ end
36
+ end
37
+ end
@@ -36,9 +36,9 @@ module Sapristi
36
36
  unless (0...monitor_width).include? x_pos
37
37
  raise Error, "x=#{x_pos} is outside of monitor width dimension=0..#{monitor_width - 1}"
38
38
  end
39
- unless (0...monitor_height).include? y_pos
40
- raise Error, "y=#{y_pos} is outside of monitor height dimension=0..#{monitor_height - 1}"
41
- end
39
+ return if (0...monitor_height).include? y_pos
40
+
41
+ raise Error, "y=#{y_pos} is outside of monitor height dimension=0..#{monitor_height - 1}"
42
42
  end
43
43
 
44
44
  def validate_work_area(normalized, monitor_width, monitor_height)
@@ -49,9 +49,9 @@ module Sapristi
49
49
  if x_end >= monitor_width
50
50
  raise Error, "window x dimensions: [#{x_pos}, #{x_end}] exceeds monitor width [0..#{monitor_width - 1}]"
51
51
  end
52
- if y_end >= monitor_height
53
- raise Error, "window y dimensions: [#{y_pos}, #{y_end}] exceeds monitor height [0..#{monitor_height - 1}]"
54
- end
52
+ return if y_end < monitor_height
53
+
54
+ raise Error, "window y dimensions: [#{y_pos}, #{y_end}] exceeds monitor height [0..#{monitor_height - 1}]"
55
55
  end
56
56
 
57
57
  MIN_X_SIZE = 50
@@ -11,8 +11,8 @@ module Sapristi
11
11
  window = get_window definition.title, definition.command
12
12
 
13
13
  @window_manager.move_resize(window,
14
- definition.x_position, definition.y_position,
15
- definition.h_size, definition.v_size)
14
+ [definition.x_position, definition.y_position,
15
+ definition.h_size, definition.v_size])
16
16
  end
17
17
 
18
18
  private
@@ -8,7 +8,7 @@ require 'gtk3'
8
8
  module Sapristi
9
9
  class MonitorManager
10
10
  def initialize
11
- @os_manager = Linux::MonitorManager.new
11
+ @os_manager = OSFactory.new.monitor_manager
12
12
  end
13
13
 
14
14
  def get_monitor_or_main(name)
@@ -3,8 +3,8 @@
3
3
  module Sapristi
4
4
  class NewProcessWindowDetector
5
5
  def initialize
6
- @display = WMCtrl.display
7
- @process_manager = Linux::ProcessManager.new
6
+ @display = OSFactory.new.window_manager
7
+ @process_manager = OSFactory.new.process_manager
8
8
  end
9
9
 
10
10
  def detect_window_for_process(command, timeout_in_seconds = 30)
@@ -25,7 +25,7 @@ module Sapristi
25
25
 
26
26
  def save_pids_and_windows
27
27
  @previous_windows_ids = @display.windows.map { |window| window[:id] }
28
- @previous_pids = process_manager.class.user_pids
28
+ @previous_pids = process_manager.user_pids
29
29
  end
30
30
 
31
31
  def wait_for_window(command, timeout_in_seconds)
@@ -49,9 +49,9 @@ module Sapristi
49
49
  end
50
50
 
51
51
  def check_user_configuration(conf_file)
52
- if conf_file.eql?(Sapristi.user_default_configuration_file) && !File.exist?(conf_file)
53
- @configuration_loader.create_empty_configuration conf_file
54
- end
52
+ return unless conf_file.eql?(Sapristi.user_default_configuration_file) && !File.exist?(conf_file)
53
+
54
+ @configuration_loader.create_empty_configuration conf_file
55
55
  end
56
56
 
57
57
  def self.user_default_configuration_file
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sapristi
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
@@ -1,43 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+
3
5
  module Sapristi
4
6
  class WindowManager
5
- def initialize
6
- @display = Linux::WindowManager.new
7
- end
7
+ extend Forwardable
8
8
 
9
- def windows
10
- @display.windows
9
+ def initialize
10
+ @display = OSFactory.new.window_manager
11
11
  end
12
12
 
13
- def close(window)
14
- @display.close(window)
15
- end
13
+ def_delegators :@display, :windows, :close, :workspaces, :move_resize, :resize, :move
16
14
 
17
15
  def find_window(title_regex)
18
16
  @display.windows title: title_regex
19
17
  end
20
18
 
21
- def move_resize(window, x_position, y_position, width, height)
22
- call_move_resize(window, [x_position, y_position, width, height])
23
- end
24
-
25
- def resize(window, width, height)
26
- actual_window = @display.windows(id: window.id).first
27
- x_position, y_position = (actual_window.exterior_frame || actual_window.geometry)[0..1]
28
- call_move_resize(window, [x_position, y_position, width, height])
29
- end
30
-
31
- def move(window, x_position, y_position)
32
- actual_window = @display.windows(id: window.id).first
33
- width, height = (actual_window.exterior_frame || actual_window.geometry)[2..3]
34
- call_move_resize(window, [x_position, y_position, width, height])
35
- end
36
-
37
- def workspaces
38
- @display.workspaces
39
- end
40
-
41
19
  def find_workspace_or_current(id)
42
20
  return workspaces.find(&:current).id unless id
43
21
 
@@ -52,32 +30,5 @@ module Sapristi
52
30
  def workspace?(id)
53
31
  workspaces.find { |workspace| workspace.id.eql? id }
54
32
  end
55
-
56
- def call_move_resize(window, requested)
57
- geometry = requested.clone
58
- left, right, top, bottom = window.frame_extents || [0, 0, 0, 0]
59
- geometry[2] -= left + right
60
- geometry[3] -= top + bottom
61
-
62
- @display.move_resize(window, geometry)
63
-
64
- check_expected_geometry window, requested
65
- end
66
-
67
- LABELS = %w[x y width heigth].freeze
68
-
69
- def check_expected_geometry(window, expected)
70
- actual_window = @display.windows(id: window.id).first
71
- actual = actual_window.exterior_frame || actual_window.geometry
72
-
73
- unless actual.eql? expected
74
- ::Sapristi.logger.warn "Geometry mismatch #{WindowManager.text_diff(actual, expected)}, requested=#{expected}, window=#{window.title}"
75
- end
76
- end
77
-
78
- def self.text_diff(actual, expected)
79
- diffs = 4.times.filter { |index| !expected[index].eql? actual[index] }
80
- diffs.map { |diff_index| "#{LABELS[diff_index]}: expected=#{expected[diff_index]}, actual=#{actual[diff_index]}" }.join(', ')
81
- end
82
33
  end
83
34
  end
@@ -56,5 +56,6 @@ Gem::Specification.new do |spec|
56
56
  spec.add_development_dependency 'simplecov', '~> 0.19.0'
57
57
 
58
58
  spec.add_runtime_dependency 'gtk3', '~> 3.4.3'
59
+ spec.add_runtime_dependency 'os', '~> 1.1.0'
59
60
  spec.add_runtime_dependency 'ruby-wmctrl', '~> 0.0.8'
60
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sapristi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sapristi dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -234,6 +234,20 @@ dependencies:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
236
  version: 3.4.3
237
+ - !ruby/object:Gem::Dependency
238
+ name: os
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - "~>"
242
+ - !ruby/object:Gem::Version
243
+ version: 1.1.0
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - "~>"
249
+ - !ruby/object:Gem::Version
250
+ version: 1.1.0
237
251
  - !ruby/object:Gem::Dependency
238
252
  name: ruby-wmctrl
239
253
  requirement: !ruby/object:Gem::Requirement
@@ -274,6 +288,7 @@ files:
274
288
  - lib/sapristi/adapters/linux/monitor_manager.rb
275
289
  - lib/sapristi/adapters/linux/process_manager.rb
276
290
  - lib/sapristi/adapters/linux/window_manager.rb
291
+ - lib/sapristi/adapters/os_factory.rb
277
292
  - lib/sapristi/arguments_parser.rb
278
293
  - lib/sapristi/attribute_normalizer.rb
279
294
  - lib/sapristi/configuration_loader.rb