sapristi 0.1.1 → 0.1.2

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