uh-wm 0.0.2.pre → 0.0.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 +4 -4
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +5 -0
- data/Guardfile +12 -0
- data/LICENSE +30 -0
- data/README.md +68 -0
- data/Rakefile +40 -0
- data/bin/uhwm +5 -0
- data/config/cucumber.yaml +1 -0
- data/features/actions/execute.feature +9 -0
- data/features/actions/layout_delegation.feature +31 -0
- data/features/actions/quit.feature +9 -0
- data/features/cli/debug.feature +5 -0
- data/features/cli/layout.feature +15 -0
- data/features/cli/require.feature +5 -0
- data/features/cli/run_control.feature +9 -0
- data/features/cli/usage.feature +11 -0
- data/features/cli/verbose.feature +5 -0
- data/features/cli/version.feature +6 -0
- data/features/cli/worker.feature +9 -0
- data/features/layout/manage.feature +12 -0
- data/features/layout/protocol.feature +24 -0
- data/features/layout/unmanage.feature +10 -0
- data/features/manager/check_other_wm.feature +8 -0
- data/features/manager/input_events.feature +8 -0
- data/features/manager/manage.feature +14 -0
- data/features/manager/unmanage.feature +13 -0
- data/features/manager/x_errors.feature +17 -0
- data/features/run_control/evaluation.feature +18 -0
- data/features/run_control/key.feature +33 -0
- data/features/run_control/modifier.feature +10 -0
- data/features/run_control/worker.feature +9 -0
- data/features/session/connection.feature +5 -0
- data/features/session/termination.feature +13 -0
- data/features/steps/filesystem_steps.rb +3 -0
- data/features/steps/output_steps.rb +44 -0
- data/features/steps/run_control_steps.rb +3 -0
- data/features/steps/run_steps.rb +41 -0
- data/features/steps/x_steps.rb +53 -0
- data/features/support/env.rb +33 -0
- data/lib/uh/wm.rb +8 -0
- data/lib/uh/wm/actions_handler.rb +46 -0
- data/lib/uh/wm/cli.rb +20 -13
- data/lib/uh/wm/client.rb +64 -0
- data/lib/uh/wm/dispatcher.rb +3 -1
- data/lib/uh/wm/env.rb +15 -9
- data/lib/uh/wm/env_logging.rb +8 -0
- data/lib/uh/wm/logger_formatter.rb +16 -0
- data/lib/uh/wm/manager.rb +96 -14
- data/lib/uh/wm/run_control.rb +8 -3
- data/lib/uh/wm/runner.rb +82 -14
- data/lib/uh/wm/testing/acceptance_helpers.rb +140 -18
- data/lib/uh/wm/version.rb +1 -1
- data/lib/uh/wm/workers.rb +21 -0
- data/lib/uh/wm/workers/base.rb +27 -0
- data/lib/uh/wm/workers/blocking.rb +11 -0
- data/lib/uh/wm/workers/mux.rb +18 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/exit_helpers.rb +6 -0
- data/spec/support/filesystem_helpers.rb +11 -0
- data/spec/uh/wm/actions_handler_spec.rb +30 -0
- data/spec/uh/wm/cli_spec.rb +214 -0
- data/spec/uh/wm/client_spec.rb +133 -0
- data/spec/uh/wm/dispatcher_spec.rb +76 -0
- data/spec/uh/wm/env_spec.rb +145 -0
- data/spec/uh/wm/manager_spec.rb +355 -0
- data/spec/uh/wm/run_control_spec.rb +102 -0
- data/spec/uh/wm/runner_spec.rb +186 -0
- data/uh-wm.gemspec +25 -0
- metadata +112 -9
@@ -0,0 +1,133 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
RSpec.describe Client do
|
4
|
+
let(:geo) { Geo.new(0, 0, 640, 480) }
|
5
|
+
let(:window) do
|
6
|
+
instance_spy Window, 'window', to_s: 'wid',
|
7
|
+
name: 'wname', wclass: 'wclass'
|
8
|
+
end
|
9
|
+
subject(:client) { described_class.new window, geo }
|
10
|
+
|
11
|
+
it 'is not visible' do
|
12
|
+
expect(client).not_to be_visible
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is hidden' do
|
16
|
+
expect(client).to be_hidden
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'has an unmap count of 0' do
|
20
|
+
expect(client.unmap_count).to eq 0
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#to_s' do
|
24
|
+
it 'includes window name' do
|
25
|
+
expect(client.to_s).to include 'wname'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'includes window class' do
|
29
|
+
expect(client.to_s).to include 'wclass'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'includes geo' do
|
33
|
+
expect(client.to_s).to include geo.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'includes window id' do
|
37
|
+
expect(client.to_s).to include 'wid'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#name' do
|
42
|
+
it 'returns the window name' do
|
43
|
+
expect(client.name).to eq window.name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#wclass' do
|
48
|
+
it 'returns the window class' do
|
49
|
+
expect(client.wclass).to eq window.wclass
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#configure' do
|
54
|
+
it 'configures the window with client geo' do
|
55
|
+
expect(window).to receive(:configure).with geo
|
56
|
+
client.configure
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns self' do
|
60
|
+
expect(client.configure).to be client
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#moveresize' do
|
65
|
+
it 'moveresizes the window with client geo' do
|
66
|
+
expect(window).to receive(:moveresize).with geo
|
67
|
+
client.moveresize
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns self' do
|
71
|
+
expect(client.moveresize).to be client
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#show' do
|
76
|
+
it 'maps the window' do
|
77
|
+
expect(window).to receive :map
|
78
|
+
client.show
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'toggles the client as visible' do
|
82
|
+
expect { client.show }
|
83
|
+
.to change { client.visible? }
|
84
|
+
.from(false).to true
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'returns self' do
|
88
|
+
expect(client.show).to be client
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#hide' do
|
93
|
+
it 'unmaps the window' do
|
94
|
+
expect(window).to receive :unmap
|
95
|
+
client.hide
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'toggles the client as hidden' do
|
99
|
+
client.show
|
100
|
+
expect { client.hide }
|
101
|
+
.to change { client.hidden? }
|
102
|
+
.from(false).to true
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'increments the unmap count' do
|
106
|
+
expect { client.hide }
|
107
|
+
.to change { client.unmap_count }
|
108
|
+
.from(0).to 1
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'returns self' do
|
112
|
+
expect(client.hide).to be client
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#focus' do
|
117
|
+
it 'raises the window' do
|
118
|
+
expect(window).to receive :raise
|
119
|
+
client.focus
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'focuses the window' do
|
123
|
+
expect(window).to receive :focus
|
124
|
+
client.focus
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns self' do
|
128
|
+
expect(client.focus).to be client
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
RSpec.describe Dispatcher do
|
4
|
+
subject(:dispatcher) { described_class.new }
|
5
|
+
|
6
|
+
describe '#[]' do
|
7
|
+
context 'when given key for existing hook' do
|
8
|
+
before { dispatcher.hooks[:hook_key] = [:hook] }
|
9
|
+
|
10
|
+
it 'returns registered hooks for this key' do
|
11
|
+
expect(dispatcher[:hook_key]).to eq [:hook]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when given multiple keys for existing hook' do
|
16
|
+
before { dispatcher.hooks[%i[hook key]] = [:hook] }
|
17
|
+
|
18
|
+
it 'returns registered hooks for this key' do
|
19
|
+
expect(dispatcher[:hook, :key]).to eq [:hook]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when given key for unknown hook' do
|
24
|
+
it 'returns an empty array' do
|
25
|
+
expect(dispatcher[:unknown_hook]).to eq []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#on' do
|
31
|
+
it 'registers given hook for given key' do
|
32
|
+
dispatcher.on(:hook_key) { :hook }
|
33
|
+
expect(dispatcher.hooks[:hook_key]).to be
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'registers given hook for given multiple keys' do
|
37
|
+
dispatcher.on(:hook, :key) { :hook }
|
38
|
+
expect(dispatcher.hooks[%i[hook key]]).to be
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#emit' do
|
43
|
+
it 'calls hooks registered for given key' do
|
44
|
+
dispatcher.on(:hook_key) { throw :hook_code }
|
45
|
+
expect { dispatcher.emit :hook_key }.to throw_symbol :hook_code
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns the value returned by a registered hook' do
|
49
|
+
dispatcher.on(:hook_key) { :hook_code }
|
50
|
+
expect(dispatcher.emit :hook_key).to eq :hook_code
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when no hooks are registered for given key' do
|
54
|
+
it 'does not call another hook' do
|
55
|
+
dispatcher.on(:hook_key) { throw :hook_code }
|
56
|
+
expect { dispatcher.emit :other_hook_key }.not_to throw_symbol
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when no hooks are registered at all' do
|
61
|
+
it 'does not raise any error' do
|
62
|
+
expect { dispatcher.emit :hook_key }.not_to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when args keyword argument is given' do
|
67
|
+
it 'calls hooks with given args' do
|
68
|
+
dispatcher.on(:hook_key) { |arg1, arg2| throw arg2 }
|
69
|
+
expect { dispatcher.emit :hook_key, args: %i[arg1 arg2] }
|
70
|
+
.to throw_symbol :arg2
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
RSpec.describe Env do
|
4
|
+
let(:output) { StringIO.new }
|
5
|
+
let(:logger) { Logger.new(StringIO.new) }
|
6
|
+
subject(:env) { described_class.new output }
|
7
|
+
|
8
|
+
it 'has verbose mode disabled' do
|
9
|
+
expect(env).not_to be_verbose
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has debug mode disabled' do
|
13
|
+
expect(env).not_to be_debug
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'has the default rc path set' do
|
17
|
+
expect(env.rc_path).to eq '~/.uhwmrc.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has no layout_class set' do
|
21
|
+
expect(env.layout_class).not_to be
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'has the default modifier set' do
|
25
|
+
expect(env.modifier).to eq :mod1
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has default key binding for quit set' do
|
29
|
+
expect(env.keybinds.keys).to include [:q, :shift]
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has the blocking worker by default' do
|
33
|
+
expect(env.worker).to eq :block
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#verbose?' do
|
37
|
+
context 'when verbose mode is disabled' do
|
38
|
+
before { env.verbose = false }
|
39
|
+
|
40
|
+
it 'returns false' do
|
41
|
+
expect(env.verbose?).to be false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when verbose mode is enabled' do
|
46
|
+
before { env.verbose = true }
|
47
|
+
|
48
|
+
it 'returns true' do
|
49
|
+
expect(env.verbose?).to be true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#debug?' do
|
55
|
+
context 'when debug mode is disabled' do
|
56
|
+
before { env.debug = false }
|
57
|
+
|
58
|
+
it 'returns false' do
|
59
|
+
expect(env.debug?).to be false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when debug mode is enabled' do
|
64
|
+
before { env.debug = true }
|
65
|
+
|
66
|
+
it 'returns true' do
|
67
|
+
expect(env.debug?).to be true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#layout' do
|
73
|
+
context 'when a layout class is set' do
|
74
|
+
let(:some_layout) { Class.new }
|
75
|
+
|
76
|
+
before { env.layout_class = some_layout }
|
77
|
+
|
78
|
+
it 'returns a new instance of this layout class' do
|
79
|
+
expect(env.layout).to be_an_instance_of some_layout
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when a layout class is not set' do
|
84
|
+
it 'returns an instance of the default layout' do
|
85
|
+
expect(env.layout).to be_an_instance_of ::Uh::Layout
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#logger' do
|
91
|
+
it 'returns a logger' do
|
92
|
+
expect(env.logger).to be_a Logger
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'has logger level warn set' do
|
96
|
+
expect(env.logger.level).to be Logger::WARN
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when verbose mode is enabled' do
|
100
|
+
before { env.verbose = true }
|
101
|
+
|
102
|
+
it 'has logger level info set' do
|
103
|
+
expect(env.logger.level).to be Logger::INFO
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when debug mode is enabled' do
|
108
|
+
before { env.debug = true }
|
109
|
+
|
110
|
+
it 'has logger level debug set' do
|
111
|
+
expect(env.logger.level).to be Logger::DEBUG
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#log' do
|
117
|
+
it 'logs given message at info level' do
|
118
|
+
expect(env.logger).to receive(:info).with 'some message'
|
119
|
+
env.log 'some message'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#log_debug' do
|
124
|
+
it 'logs given message at debug level' do
|
125
|
+
expect(env.logger).to receive(:debug).with 'some message'
|
126
|
+
env.log_debug 'some message'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#log_logger_level' do
|
131
|
+
it 'logs the logger level' do
|
132
|
+
expect(env.logger).to receive(:info).with /log.+(warn|info|debug).+level/i
|
133
|
+
env.log_logger_level
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#print' do
|
138
|
+
it 'prints the message to the output' do
|
139
|
+
env.print 'some message'
|
140
|
+
expect(output.string).to eq 'some message'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
module Uh
|
2
|
+
module WM
|
3
|
+
RSpec.describe Manager do
|
4
|
+
let(:block) { proc { } }
|
5
|
+
let(:window) { instance_spy Window, override_redirect?: false }
|
6
|
+
let(:events) { Dispatcher.new }
|
7
|
+
let(:modifier) { :mod1 }
|
8
|
+
let(:display) { Display.new }
|
9
|
+
subject(:manager) { described_class.new events, modifier, display }
|
10
|
+
|
11
|
+
it 'has a new display' do
|
12
|
+
expect(manager.display).to be_a Display
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has no clients' do
|
16
|
+
expect(manager.clients).to be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#to_io', :xvfb do
|
20
|
+
context 'when connected' do
|
21
|
+
before { manager.connect }
|
22
|
+
|
23
|
+
it 'returns an IO object wrapping the display file descriptor' do
|
24
|
+
expect(manager.to_io)
|
25
|
+
.to be_an(IO)
|
26
|
+
.and have_attributes(fileno: display.fileno)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#connect', :xvfb do
|
32
|
+
it 'opens the display' do
|
33
|
+
expect(manager.display).to receive(:open).and_call_original
|
34
|
+
manager.connect
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'emits :connecting event with the display' do
|
38
|
+
events.on :connecting, &block
|
39
|
+
expect(block).to receive(:call) do |*args|
|
40
|
+
expect(args).to eq [display]
|
41
|
+
end
|
42
|
+
manager.connect
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'emits :connected event with the display' do
|
46
|
+
events.on :connected, &block
|
47
|
+
expect(block).to receive(:call) do |*args|
|
48
|
+
expect(args).to eq [display]
|
49
|
+
end
|
50
|
+
manager.connect
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'updates the root window mask in order to manage windows' do
|
54
|
+
manager.connect
|
55
|
+
expect(display.root.mask).to eq Events::PROPERTY_CHANGE_MASK |
|
56
|
+
Events::SUBSTRUCTURE_REDIRECT_MASK |
|
57
|
+
Events::SUBSTRUCTURE_NOTIFY_MASK |
|
58
|
+
Events::STRUCTURE_NOTIFY_MASK
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when connection fails' do
|
62
|
+
before { allow(display).to receive(:open) { fail } }
|
63
|
+
|
64
|
+
it 'does not emit :connected event' do
|
65
|
+
events.on :connected, &block
|
66
|
+
expect(block).not_to receive :call
|
67
|
+
manager.connect rescue nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#disconnect' do
|
73
|
+
it 'closes the display' do
|
74
|
+
expect(display).to receive :close
|
75
|
+
manager.disconnect
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'emits :disconnected event' do
|
79
|
+
allow(display).to receive :close
|
80
|
+
events.on :disconnected, &block
|
81
|
+
expect(block).to receive :call
|
82
|
+
manager.disconnect
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#flush' do
|
87
|
+
it 'flushes the display' do
|
88
|
+
expect(display).to receive :flush
|
89
|
+
manager.flush
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#grab_key' do
|
94
|
+
it 'grabs given key on the display' do
|
95
|
+
expect(manager.display)
|
96
|
+
.to receive(:grab_key).with('f', KEY_MODIFIERS[modifier])
|
97
|
+
manager.grab_key :f
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when a modifier is given' do
|
101
|
+
it 'grabs the key with given modifier' do
|
102
|
+
expect(manager.display)
|
103
|
+
.to receive(:grab_key)
|
104
|
+
.with('f', KEY_MODIFIERS[modifier] | KEY_MODIFIERS[:shift])
|
105
|
+
manager.grab_key :f, :shift
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#configure' do
|
111
|
+
context 'with new window' do
|
112
|
+
it 'sends a configure event to the window with a default geo' do
|
113
|
+
expect(window)
|
114
|
+
.to receive(:configure_event).with(Geo.new(0, 0, 320, 240))
|
115
|
+
manager.configure window
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'when :configure event returns a geo' do
|
119
|
+
it 'sends a configure event with geo returned by event' do
|
120
|
+
geo = Geo.new(0, 0, 42, 42)
|
121
|
+
events.on(:configure) { geo }
|
122
|
+
expect(window).to receive(:configure_event).with geo
|
123
|
+
manager.configure window
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with known window' do
|
129
|
+
before { manager.map window }
|
130
|
+
|
131
|
+
it 'tells the client to configure' do
|
132
|
+
expect(manager.clients[0]).to receive :configure
|
133
|
+
manager.configure window
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#map' do
|
139
|
+
it 'registers a new client wrapping the given window' do
|
140
|
+
manager.map window
|
141
|
+
expect(manager.clients[0])
|
142
|
+
.to be_a(Client)
|
143
|
+
.and have_attributes(window: window)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'registers new client only once for a given window' do
|
147
|
+
manager.map window
|
148
|
+
expect { manager.map window }.not_to change { manager.clients }
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'ignores event when window has override redirect' do
|
152
|
+
allow(window).to receive(:override_redirect?) { true }
|
153
|
+
expect { manager.map window }.not_to change { manager.clients }
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'emits :manage event with the registered client' do
|
157
|
+
events.on :manage, &block
|
158
|
+
expect(block).to receive :call do |client|
|
159
|
+
expect(client)
|
160
|
+
.to be_a(Client)
|
161
|
+
.and have_attributes(window: window)
|
162
|
+
end
|
163
|
+
manager.map window
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '#unmap' do
|
168
|
+
before { manager.map window }
|
169
|
+
|
170
|
+
context 'when client unmap count is 0 or less' do
|
171
|
+
it 'preserves the client unmap count' do
|
172
|
+
client = manager.clients[0]
|
173
|
+
expect { manager.unmap window }
|
174
|
+
.not_to change { client.unmap_count }
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'unregisters the client' do
|
178
|
+
expect { manager.unmap window }
|
179
|
+
.to change { manager.clients.size }.from(1).to 0
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'emits :unmanage event with the client' do
|
183
|
+
events.on :unmanage, &block
|
184
|
+
expect(block).to receive(:call).with manager.clients[0]
|
185
|
+
manager.unmap window
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'when client unmap count is strictly positive' do
|
190
|
+
before { manager.clients[0].unmap_count += 1 }
|
191
|
+
|
192
|
+
it 'does not unregister the client' do
|
193
|
+
expect { manager.unmap window }.not_to change { manager.clients }
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'decrements the unmap count' do
|
197
|
+
manager.unmap window
|
198
|
+
expect(manager.clients[0].unmap_count).to eq 0
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'with unknown window' do
|
203
|
+
let(:unknown_window) { window.dup }
|
204
|
+
|
205
|
+
it 'does not change registered clients' do
|
206
|
+
expect { manager.unmap unknown_window }
|
207
|
+
.not_to change { manager.clients }
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'does not emit any event' do
|
211
|
+
expect(events).not_to receive :emit
|
212
|
+
manager.unmap unknown_window
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#destroy' do
|
218
|
+
before { manager.map window }
|
219
|
+
|
220
|
+
it 'unregisters the client' do
|
221
|
+
expect { manager.destroy window }
|
222
|
+
.to change { manager.clients.size }.from(1).to 0
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'emits :unmanage event with the client' do
|
226
|
+
events.on :unmanage, &block
|
227
|
+
expect(block).to receive(:call).with manager.clients[0]
|
228
|
+
manager.destroy window
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'with unknown window' do
|
232
|
+
let(:unknown_window) { window.dup }
|
233
|
+
|
234
|
+
it 'does not change registered clients' do
|
235
|
+
expect { manager.destroy unknown_window }
|
236
|
+
.not_to change { manager.clients }
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'does not emit any event' do
|
240
|
+
expect(events).not_to receive :emit
|
241
|
+
manager.destroy unknown_window
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe '#handle_next_event' do
|
247
|
+
it 'handles the next available event on display' do
|
248
|
+
event = double 'event'
|
249
|
+
allow(display).to receive(:next_event) { event }
|
250
|
+
expect(manager).to receive(:handle).with(event).once
|
251
|
+
manager.handle_next_event
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe '#handle_pending_events' do
|
256
|
+
let(:event) { double 'event' }
|
257
|
+
|
258
|
+
context 'when an event is pending on display' do
|
259
|
+
before do
|
260
|
+
allow(display).to receive(:pending?).and_return true, false
|
261
|
+
allow(display).to receive(:next_event) { event }
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'handles the event' do
|
265
|
+
expect(manager).to receive(:handle).with(event).once
|
266
|
+
manager.handle_pending_events
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'when multiple events are pending on display' do
|
271
|
+
before do
|
272
|
+
allow(display).to receive(:pending?).and_return true, true, false
|
273
|
+
allow(display).to receive(:next_event) { event }
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'handles all pending events' do
|
277
|
+
expect(manager).to receive(:handle).with(event).twice
|
278
|
+
manager.handle_pending_events
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe '#handle' do
|
284
|
+
let(:event) { double 'event', type: :any }
|
285
|
+
|
286
|
+
it 'emits :xevent event with the X event' do
|
287
|
+
events.on :xevent, &block
|
288
|
+
manager.handle event
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'when key_press event is given' do
|
292
|
+
let(:mod_mask) { KEY_MODIFIERS[modifier] }
|
293
|
+
let(:event) do
|
294
|
+
double 'event',
|
295
|
+
type: :key_press,
|
296
|
+
key: 'f',
|
297
|
+
modifier_mask: mod_mask
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'emits :key event with the corresponding key' do
|
301
|
+
events.on(:key, :f) { throw :key_press_code }
|
302
|
+
expect { manager.handle event }.to throw_symbol :key_press_code
|
303
|
+
end
|
304
|
+
|
305
|
+
context 'whith shift key modifier' do
|
306
|
+
let(:mod_mask) { KEY_MODIFIERS[modifier] | KEY_MODIFIERS[:shift] }
|
307
|
+
|
308
|
+
it 'emits :key event with the corresponding key and :shift' do
|
309
|
+
events.on(:key, :f, :shift) { throw :key_press_code }
|
310
|
+
expect { manager.handle event }.to throw_symbol :key_press_code
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'when configure request event is given' do
|
316
|
+
let(:event) do
|
317
|
+
double 'event', type: :configure_request, window: :window
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'configures the event window' do
|
321
|
+
expect(manager).to receive(:configure).with :window
|
322
|
+
manager.handle event
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'when destroy_notify event is given' do
|
327
|
+
let(:event) { double 'event', type: :destroy_notify, window: :window }
|
328
|
+
|
329
|
+
it 'destroy the event window' do
|
330
|
+
expect(manager).to receive(:destroy).with :window
|
331
|
+
manager.handle event
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context 'when map_request event is given' do
|
336
|
+
let(:event) { double 'event', type: :map_request, window: :window }
|
337
|
+
|
338
|
+
it 'maps the event window' do
|
339
|
+
expect(manager).to receive(:map).with :window
|
340
|
+
manager.handle event
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
context 'when unmap_notify event is given' do
|
345
|
+
let(:event) { double 'event', type: :unmap_notify, window: :window }
|
346
|
+
|
347
|
+
it 'unmap the event window' do
|
348
|
+
expect(manager).to receive(:unmap).with :window
|
349
|
+
manager.handle event
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|