Merge branch 'window-unmap-handling'
Handle unmap notify event in the manager, generate :unmanage events with the client, and forward them to the layout.
This commit is contained in:
commit
a15af6f0ab
10
features/layout/unmanage.feature
Normal file
10
features/layout/unmanage.feature
Normal file
@ -0,0 +1,10 @@
|
||||
Feature: layout client unmanagement
|
||||
|
||||
Background:
|
||||
Given uhwm is running
|
||||
And a first window is mapped
|
||||
And a second window is mapped
|
||||
|
||||
Scenario: maps another window
|
||||
When the second window requests to be unmapped
|
||||
Then the first window must be mapped
|
@ -1,3 +1,7 @@
|
||||
Given /^a (\w+) window is mapped$/ do |ident|
|
||||
x_window_map ident: ident
|
||||
end
|
||||
|
||||
When /^I press the ([^ ]+) keys?$/ do |keys|
|
||||
x_key keys
|
||||
end
|
||||
@ -6,6 +10,10 @@ When /^a window requests to be mapped$/ do
|
||||
x_window_map
|
||||
end
|
||||
|
||||
When /^the (\w+) window requests to be unmapped$/ do |ident|
|
||||
x_window_unmap ident: ident
|
||||
end
|
||||
|
||||
When /^a window requests to be mapped (\d+) times$/ do |times|
|
||||
x_window_map times: times.to_i
|
||||
end
|
||||
@ -19,6 +27,10 @@ Then /^the window must be mapped$/ do
|
||||
expect(x_window_map_state).to eq 'IsViewable'
|
||||
end
|
||||
|
||||
Then /^the (\w+) window must be mapped$/ do |ident|
|
||||
expect(x_window_map_state ident: ident).to eq 'IsViewable'
|
||||
end
|
||||
|
||||
Then /^the window must be focused$/ do
|
||||
expect(x_focused_window_id).to eq x_window_id
|
||||
end
|
||||
|
@ -1,8 +1,8 @@
|
||||
module Uh
|
||||
module WM
|
||||
class Client
|
||||
attr_reader :window, :unmap_count
|
||||
attr_accessor :geo
|
||||
attr_reader :window
|
||||
attr_accessor :geo, :unmap_count
|
||||
|
||||
def initialize window, geo = nil
|
||||
@window = window
|
||||
|
@ -61,6 +61,16 @@ module Uh
|
||||
@events.emit :manage, args: client
|
||||
end
|
||||
|
||||
def unmap window
|
||||
return unless client = client_for(window)
|
||||
if client.unmap_count > 0
|
||||
client.unmap_count -= 1
|
||||
else
|
||||
@clients.delete client
|
||||
@events.emit :unmanage, args: client
|
||||
end
|
||||
end
|
||||
|
||||
def handle_next_event
|
||||
handle @display.next_event
|
||||
end
|
||||
@ -97,6 +107,10 @@ module Uh
|
||||
map event.window
|
||||
end
|
||||
|
||||
def handle_unmap_notify event
|
||||
unmap event.window
|
||||
end
|
||||
|
||||
def client_for window
|
||||
@clients.find { |e| e.window == window }
|
||||
end
|
||||
|
@ -115,6 +115,10 @@ module Uh
|
||||
log "Managing client #{client}"
|
||||
layout << client
|
||||
end
|
||||
@events.on :unmanage do |client|
|
||||
log "Unmanaging client #{client}"
|
||||
layout.remove client
|
||||
end
|
||||
end
|
||||
|
||||
def register_keybinds_hooks
|
||||
|
@ -56,8 +56,9 @@ module Uh
|
||||
@other_wm
|
||||
end
|
||||
|
||||
def x_client
|
||||
@x_client ||= XClient.new
|
||||
def x_client ident: :default
|
||||
@x_clients ||= {}
|
||||
@x_clients[ident] ||= XClient.new(ident)
|
||||
end
|
||||
|
||||
def x_focused_window_id
|
||||
@ -81,25 +82,30 @@ module Uh
|
||||
end.any?
|
||||
end
|
||||
|
||||
def x_window_id
|
||||
@x_client.window_id
|
||||
def x_window_id **options
|
||||
x_client(options).window_id
|
||||
end
|
||||
|
||||
def x_window_name
|
||||
@x_client.window_name
|
||||
x_client.window_name
|
||||
end
|
||||
|
||||
def x_window_map times: 1
|
||||
times.times { x_client.map }
|
||||
x_client.sync
|
||||
def x_window_map times: 1, **options
|
||||
times.times { x_client(options).map }
|
||||
x_client(options).sync
|
||||
end
|
||||
|
||||
def x_window_map_state
|
||||
`xwininfo -id #{x_window_id}`[/Map State: (\w+)/, 1]
|
||||
def x_window_map_state **options
|
||||
`xwininfo -id #{x_window_id options}`[/Map State: (\w+)/, 1]
|
||||
end
|
||||
|
||||
def x_window_unmap options
|
||||
x_client(options).unmap
|
||||
x_client(options).sync
|
||||
end
|
||||
|
||||
def x_clients_ensure_stop
|
||||
@x_client and @x_client.terminate
|
||||
@x_clients and @x_clients.any? and @x_clients.values.each &:terminate
|
||||
end
|
||||
|
||||
|
||||
@ -132,8 +138,8 @@ module Uh
|
||||
class XClient
|
||||
attr_reader :name
|
||||
|
||||
def initialize
|
||||
@name = "#{self.class.name.split('::').last}/#{object_id}"
|
||||
def initialize name = object_id
|
||||
@name = "#{self.class.name.split('::').last}/#{name}"
|
||||
@geo = Geo.new(0, 0, 640, 480)
|
||||
@display = Display.new.tap { |o| o.open }
|
||||
end
|
||||
@ -164,6 +170,11 @@ module Uh
|
||||
window.map
|
||||
self
|
||||
end
|
||||
|
||||
def unmap
|
||||
window.unmap
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -164,6 +164,56 @@ module Uh
|
||||
end
|
||||
end
|
||||
|
||||
describe '#unmap' do
|
||||
before { manager.map window }
|
||||
|
||||
context 'when client unmap count is 0 or less' do
|
||||
it 'preserves the client unmap count' do
|
||||
client = manager.clients[0]
|
||||
expect { manager.unmap window }
|
||||
.not_to change { client.unmap_count }
|
||||
end
|
||||
|
||||
it 'unregisters the client' do
|
||||
expect { manager.unmap window }
|
||||
.to change { manager.clients.size }.from(1).to 0
|
||||
end
|
||||
|
||||
it 'emits :unmanage event with the client' do
|
||||
events.on :unmanage, &block
|
||||
expect(block).to receive(:call).with manager.clients[0]
|
||||
manager.unmap window
|
||||
end
|
||||
end
|
||||
|
||||
context 'when client unmap count is strictly positive' do
|
||||
before { manager.clients[0].unmap_count += 1 }
|
||||
|
||||
it 'does not unregister the client' do
|
||||
expect { manager.unmap window }.not_to change { manager.clients }
|
||||
end
|
||||
|
||||
it 'decrements the unmap count' do
|
||||
manager.unmap window
|
||||
expect(manager.clients[0].unmap_count).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unknown window' do
|
||||
let(:unknown_window) { window.dup }
|
||||
|
||||
it 'does not change registered clients' do
|
||||
expect { manager.unmap unknown_window }
|
||||
.not_to change { manager.clients }
|
||||
end
|
||||
|
||||
it 'does not emit any event' do
|
||||
expect(events).not_to receive :emit
|
||||
manager.unmap unknown_window
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#handle_next_event' do
|
||||
it 'handles the next available event on display' do
|
||||
event = double 'event'
|
||||
@ -252,6 +302,15 @@ module Uh
|
||||
manager.handle event
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unmap_notify event is given' do
|
||||
let(:event) { double 'event', type: :unmap_notify, window: :window }
|
||||
|
||||
it 'unmap the event window' do
|
||||
expect(manager).to receive(:unmap).with :window
|
||||
manager.handle event
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2,6 +2,7 @@ SomeLayout = Class.new do
|
||||
define_method(:register) { |*args| }
|
||||
define_method(:suggest_geo) { Uh::Geo.new(0, 0, 42, 42) }
|
||||
define_method(:<<) { |*args| }
|
||||
define_method(:remove) { |*args| }
|
||||
end
|
||||
|
||||
module Uh
|
||||
@ -93,6 +94,12 @@ module Uh
|
||||
expect(env.layout).to receive(:<<).with :client
|
||||
runner.events.emit :manage, args: :client
|
||||
end
|
||||
|
||||
it 'registers for :unmanage event' do
|
||||
runner.register_event_hooks
|
||||
expect(env.layout).to receive(:remove).with :client
|
||||
runner.events.emit :unmanage, args: :client
|
||||
end
|
||||
end
|
||||
|
||||
context 'keys hooks' do
|
||||
|
Loading…
x
Reference in New Issue
Block a user