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|
|
When /^I press the ([^ ]+) keys?$/ do |keys|
|
||||||
x_key keys
|
x_key keys
|
||||||
end
|
end
|
||||||
@ -6,6 +10,10 @@ When /^a window requests to be mapped$/ do
|
|||||||
x_window_map
|
x_window_map
|
||||||
end
|
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|
|
When /^a window requests to be mapped (\d+) times$/ do |times|
|
||||||
x_window_map times: times.to_i
|
x_window_map times: times.to_i
|
||||||
end
|
end
|
||||||
@ -19,6 +27,10 @@ Then /^the window must be mapped$/ do
|
|||||||
expect(x_window_map_state).to eq 'IsViewable'
|
expect(x_window_map_state).to eq 'IsViewable'
|
||||||
end
|
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
|
Then /^the window must be focused$/ do
|
||||||
expect(x_focused_window_id).to eq x_window_id
|
expect(x_focused_window_id).to eq x_window_id
|
||||||
end
|
end
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
module Uh
|
module Uh
|
||||||
module WM
|
module WM
|
||||||
class Client
|
class Client
|
||||||
attr_reader :window, :unmap_count
|
attr_reader :window
|
||||||
attr_accessor :geo
|
attr_accessor :geo, :unmap_count
|
||||||
|
|
||||||
def initialize window, geo = nil
|
def initialize window, geo = nil
|
||||||
@window = window
|
@window = window
|
||||||
|
@ -61,6 +61,16 @@ module Uh
|
|||||||
@events.emit :manage, args: client
|
@events.emit :manage, args: client
|
||||||
end
|
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
|
def handle_next_event
|
||||||
handle @display.next_event
|
handle @display.next_event
|
||||||
end
|
end
|
||||||
@ -97,6 +107,10 @@ module Uh
|
|||||||
map event.window
|
map event.window
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_unmap_notify event
|
||||||
|
unmap event.window
|
||||||
|
end
|
||||||
|
|
||||||
def client_for window
|
def client_for window
|
||||||
@clients.find { |e| e.window == window }
|
@clients.find { |e| e.window == window }
|
||||||
end
|
end
|
||||||
|
@ -115,6 +115,10 @@ module Uh
|
|||||||
log "Managing client #{client}"
|
log "Managing client #{client}"
|
||||||
layout << client
|
layout << client
|
||||||
end
|
end
|
||||||
|
@events.on :unmanage do |client|
|
||||||
|
log "Unmanaging client #{client}"
|
||||||
|
layout.remove client
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_keybinds_hooks
|
def register_keybinds_hooks
|
||||||
|
@ -56,8 +56,9 @@ module Uh
|
|||||||
@other_wm
|
@other_wm
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_client
|
def x_client ident: :default
|
||||||
@x_client ||= XClient.new
|
@x_clients ||= {}
|
||||||
|
@x_clients[ident] ||= XClient.new(ident)
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_focused_window_id
|
def x_focused_window_id
|
||||||
@ -81,25 +82,30 @@ module Uh
|
|||||||
end.any?
|
end.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_window_id
|
def x_window_id **options
|
||||||
@x_client.window_id
|
x_client(options).window_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_window_name
|
def x_window_name
|
||||||
@x_client.window_name
|
x_client.window_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_window_map times: 1
|
def x_window_map times: 1, **options
|
||||||
times.times { x_client.map }
|
times.times { x_client(options).map }
|
||||||
x_client.sync
|
x_client(options).sync
|
||||||
end
|
end
|
||||||
|
|
||||||
def x_window_map_state
|
def x_window_map_state **options
|
||||||
`xwininfo -id #{x_window_id}`[/Map State: (\w+)/, 1]
|
`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
|
end
|
||||||
|
|
||||||
def x_clients_ensure_stop
|
def x_clients_ensure_stop
|
||||||
@x_client and @x_client.terminate
|
@x_clients and @x_clients.any? and @x_clients.values.each &:terminate
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -132,8 +138,8 @@ module Uh
|
|||||||
class XClient
|
class XClient
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
def initialize
|
def initialize name = object_id
|
||||||
@name = "#{self.class.name.split('::').last}/#{object_id}"
|
@name = "#{self.class.name.split('::').last}/#{name}"
|
||||||
@geo = Geo.new(0, 0, 640, 480)
|
@geo = Geo.new(0, 0, 640, 480)
|
||||||
@display = Display.new.tap { |o| o.open }
|
@display = Display.new.tap { |o| o.open }
|
||||||
end
|
end
|
||||||
@ -164,6 +170,11 @@ module Uh
|
|||||||
window.map
|
window.map
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unmap
|
||||||
|
window.unmap
|
||||||
|
self
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -164,6 +164,56 @@ module Uh
|
|||||||
end
|
end
|
||||||
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
|
describe '#handle_next_event' do
|
||||||
it 'handles the next available event on display' do
|
it 'handles the next available event on display' do
|
||||||
event = double 'event'
|
event = double 'event'
|
||||||
@ -252,6 +302,15 @@ module Uh
|
|||||||
manager.handle event
|
manager.handle event
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,6 +2,7 @@ SomeLayout = Class.new do
|
|||||||
define_method(:register) { |*args| }
|
define_method(:register) { |*args| }
|
||||||
define_method(:suggest_geo) { Uh::Geo.new(0, 0, 42, 42) }
|
define_method(:suggest_geo) { Uh::Geo.new(0, 0, 42, 42) }
|
||||||
define_method(:<<) { |*args| }
|
define_method(:<<) { |*args| }
|
||||||
|
define_method(:remove) { |*args| }
|
||||||
end
|
end
|
||||||
|
|
||||||
module Uh
|
module Uh
|
||||||
@ -93,6 +94,12 @@ module Uh
|
|||||||
expect(env.layout).to receive(:<<).with :client
|
expect(env.layout).to receive(:<<).with :client
|
||||||
runner.events.emit :manage, args: :client
|
runner.events.emit :manage, args: :client
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
context 'keys hooks' do
|
context 'keys hooks' do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user