uh-wm 0.0.2.pre → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|