Merge branch 'client-killing'

This commit is contained in:
Thibault Jouan 2015-04-29 02:44:44 +00:00
commit 8a490e155f
9 changed files with 116 additions and 5 deletions

View File

@ -0,0 +1,11 @@
Feature: `kill' action keyword
@icccm_window
Scenario: kills current client
Given uhwm is running with this run control file:
"""
key(:f) { kill_current }
"""
And an ICCCM compliant window is mapped
When I press the alt+f keys
Then the ICCCM window must be unmapped by the manager

View File

@ -1,3 +1,10 @@
Given /^an ICCCM compliant window is mapped$/ do
icccm_window_start
timeout_until 'window not mapped after %d seconds' do
x_window_map_state(icccm_window_name) == 'IsViewable'
end
end
Given /^a(?:\s(\w+))? window is mapped$/ do |ident| Given /^a(?:\s(\w+))? window is mapped$/ do |ident|
x_client(ident).map.sync x_client(ident).map.sync
timeout_until 'window not mapped after %d seconds' do timeout_until 'window not mapped after %d seconds' do
@ -42,6 +49,10 @@ Then /^the(?:\s(\w+))? window must be mapped$/ do |ident|
end end
end end
Then /^the ICCCM window must be unmapped by the manager$/ do
uhwm_wait_output /unmanag.+#{icccm_window_name}/i
end
Then /^the window must be focused$/ do Then /^the window must be focused$/ do
timeout_until 'window not focused after %d seconds' do timeout_until 'window not focused after %d seconds' do
x_focused_window_id == x_client.window_id x_focused_window_id == x_client.window_id

View File

@ -28,6 +28,10 @@ Around '@other_wm_running' do |_, block|
with_other_wm { block.call } with_other_wm { block.call }
end end
After '@icccm_window' do
icccm_window_ensure_stop
end
if ENV.key? 'TRAVIS' if ENV.key? 'TRAVIS'
ENV['UHWMTEST_TIMEOUT'] = 8.to_s ENV['UHWMTEST_TIMEOUT'] = 8.to_s
end end

View File

@ -38,6 +38,10 @@ module Uh
Process.waitpid pid Process.waitpid pid
end end
def kill_current
layout.current_client.kill
end
def log_separator def log_separator
log '- ' * 24 log '- ' * 24
end end

View File

@ -66,6 +66,20 @@ module Uh
@window.focus @window.focus
self self
end end
def kill
if @window.icccm_wm_protocols.include? :WM_DELETE_WINDOW
@window.icccm_wm_delete
else
@window.kill
end
self
end
def kill!
window.kill
self
end
end end
end end
end end

View File

@ -8,6 +8,19 @@ module Uh
QUIT_KEYBINDING = 'alt+shift+q'.freeze QUIT_KEYBINDING = 'alt+shift+q'.freeze
LOG_READY = 'Working events'.freeze LOG_READY = 'Working events'.freeze
def icccm_window_start
@icccm_window = ChildProcess.build(*%w[xmessage window])
@icccm_window.start
end
def icccm_window_ensure_stop
@icccm_window.stop
end
def icccm_window_name
'xmessage'
end
def uhwm_run options = '-v' def uhwm_run options = '-v'
command = %w[uhwm] command = %w[uhwm]
command << options if options command << options if options
@ -89,8 +102,14 @@ expected `#{message}' (#{times}) not seen after #{e.timeout} seconds in:
fail "cannot simulate X key `#{k}'" unless system "xdotool key #{k}" fail "cannot simulate X key `#{k}'" unless system "xdotool key #{k}"
end end
def x_window_map_state window_id def x_window_map_state window_selector
`xwininfo -id #{window_id}`[/Map State: (\w+)/, 1] select_args = case window_selector
when Integer then "-id #{window_selector}"
when String then "-name #{window_selector}"
else fail ArgumentError,
"not an Integer nor a String: `#{window_selector.inspect}'"
end
`xwininfo #{select_args} 2> /dev/null`[/Map State: (\w+)/, 1]
end end

View File

@ -17,11 +17,12 @@ module Factories
modifier_mask: modifier_mask modifier_mask: modifier_mask
end end
def mock_window override_redirect: false def mock_window override_redirect: false, icccm_wm_protocols: []
instance_spy Uh::Window, 'window', instance_spy Uh::Window, 'window',
to_s: 'wid', to_s: 'wid',
name: 'wname', name: 'wname',
wclass: 'wclass', wclass: 'wclass',
override_redirect?: override_redirect override_redirect?: override_redirect,
icccm_wm_protocols: icccm_wm_protocols
end end
end end

View File

@ -24,6 +24,21 @@ module Uh
end end
end end
describe '#kill_current' do
let(:client) { instance_spy Client }
context 'when layout has a client' do
before do
allow(actions.layout).to receive(:current_client) { client }
end
it 'kills layout current client' do
expect(client).to receive :kill
actions.kill_current
end
end
end
describe '#log_separator' do describe '#log_separator' do
it 'logs a separator' do it 'logs a separator' do
expect(env).to receive(:log).with /(?:- ){20,}/ expect(env).to receive(:log).with /(?:- ){20,}/

View File

@ -1,7 +1,8 @@
module Uh module Uh
module WM module WM
RSpec.describe Client do RSpec.describe Client do
let(:window) { mock_window } let(:protocols) { [] }
let(:window) { mock_window icccm_wm_protocols: protocols }
let(:geo) { build_geo } let(:geo) { build_geo }
subject(:client) { described_class.new window, geo } subject(:client) { described_class.new window, geo }
@ -143,6 +144,37 @@ module Uh
expect(client.focus).to be client expect(client.focus).to be client
end end
end end
describe '#kill' do
it 'kills the window' do
expect(window).to receive :kill
client.kill
end
it 'returns self' do
expect(client.kill).to be client
end
context 'when window supports icccm wm delete' do
let(:protocols) { [:WM_DELETE_WINDOW] }
it 'icccm deletes the window' do
expect(window).to receive :icccm_wm_delete
client.kill
end
end
end
describe '#kill!' do
it 'kills the window' do
expect(window).to receive :kill
client.kill!
end
it 'returns self' do
expect(client.kill!).to be client
end
end
end end
end end
end end