class Sapristi::NewProcessWindowDetector

Attributes

log[R]
previous_pids[R]
previous_windows_ids[R]
process_manager[R]

Public Class Methods

new() click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 5
def initialize
  @display = OSFactory.new.window_manager
  @process_manager = OSFactory.new.process_manager
  @log = ::Sapristi.logger
end

Public Instance Methods

detect_window_for_process(command, title, timeout_in_seconds = 30) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 11
def detect_window_for_process(command, title, timeout_in_seconds = 30)
  save_pids_and_windows

  process_window = wait_for_window(command, title, timeout_in_seconds)

  if process_window
    ::Sapristi.logger.info "  Found window title=#{process_window.title} for process=#{process_window.pid}!"
  end

  process_window
end

Private Instance Methods

detect_new_windows() click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 99
def detect_new_windows
  new_windows = @display.windows.filter { |window| new_window?(window) }

  new_windows.each { |window| ::Sapristi.logger.debug "  Found new window=#{window.pid}: #{window.title}" }
end
discover_window(waiter, program, title, timeout_in_seconds) click to toggle source

This method smells of :reek:DuplicateMethodCall This method smells of :reek:LongParameterList

# File lib/sapristi/new_process_window_detector.rb, line 46
def discover_window(waiter, program, title, timeout_in_seconds)
  start_time = Time.now

  while Time.now - start_time < timeout_in_seconds # && waiter.alive?
    new_window = detect_new_windows.find { |window| window_for?(waiter, program, title, window) }

    return new_window if new_window && !splash?(new_window)

    sleep 0.2
  end
end
new_window?(window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 105
def new_window?(window)
  !previous_windows_ids.include?(window.id)
end
save_pids_and_windows() click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 27
def save_pids_and_windows
  @previous_windows_ids = @display.windows.map { |window| window[:id] }
  @previous_pids = process_manager.user_pids
end
skip_pager?(window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 117
def skip_pager?(window)
  window.state.include? '_NET_WM_STATE_SKIP_PAGER'
end
skip_taskbar?(window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 113
def skip_taskbar?(window)
  window.state.include? '_NET_WM_STATE_SKIP_TASKBAR'
end
splash?(window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 109
def splash?(window)
  skip_taskbar?(window) || skip_pager?(window)
end
wait_for_window(command, title, timeout_in_seconds) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 32
def wait_for_window(command, title, timeout_in_seconds)
  program = command.split[0]
  waiter = process_manager.execute_and_detach command, '/tmp/sapristi.stdout', '/tmp/sapristi.stderr'

  window = discover_window(waiter, program, title, timeout_in_seconds)
  return window if window

  raise Error, 'Error executing process, is dead' unless waiter.alive?

  process_manager.kill waiter
end
window_for?(waiter, program, title, window) click to toggle source

This method smells of :reek:DuplicateMethodCall This method smells of :reek:FeatureEnvy This method smells of :reek:LongParameterList This method smells of :reek:TooManyStatements

# File lib/sapristi/new_process_window_detector.rb, line 62
def window_for?(waiter, program, title, window)
  window_pgroup = Process.getpgid(window.pid)
  log.debug "Found new window: pid=#{window.pid}, ppid=#{window_pgroup}, id=#{window.id}, title=#{window.title}"
  if window_for_waiter?(waiter, window)
    log.debug "Found window by pid=#{waiter.pid}, id=#{window.id}, title=#{window.title}"
    true
  elsif window_for_process_group?(window)
    log.debug "Found window by process group=#{Process.getpgid(window.pid)}, id=#{window.id}, title=#{window.title}"
    true
  elsif window_for_command?(window, program)
    log.debug "Found window by program=#{program}, id=#{window.id}, title=#{window.title}"
    true
  elsif window_for_title?(window, title)
    log.debug "Found window by title=#{title}, id=#{window.id}, title=#{window.title}"
    true
  else
    log.warn "We can not be sure window '#{window.title}' with pid=#{window.pid} is related to program=#{program}, pid=#{waiter.pid}, status=#{waiter.status || 'dead'}"
    false
  end
end
window_for_command?(window, program) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 95
def window_for_command?(window, program)
  process_manager.cmd_for_pid(window.pid).start_with?(program)
end
window_for_process_group?(window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 91
def window_for_process_group?(window)
  Process.getpgid(window.pid).eql?(Process.getpgrp)
end
window_for_title?(window, title) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 83
def window_for_title?(window, title)
  /#{title}/i.match(window.title)
end
window_for_waiter?(waiter, window) click to toggle source
# File lib/sapristi/new_process_window_detector.rb, line 87
def window_for_waiter?(waiter, window)
  window.pid.eql?(waiter.pid)
end