uh 1.2.3 → 2.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/uh/display.c +6 -2
- data/ext/uh/uh.c +1 -5
- data/ext/uh/uh.h +1 -5
- data/ext/uh/window.c +0 -39
- data/lib/uh.rb +0 -1
- data/lib/uh/display.rb +0 -4
- data/lib/uh/version.rb +1 -1
- data/lib/uh/window.rb +0 -4
- data/uh.gemspec +0 -1
- metadata +6 -19
- data/lib/uh/wm.rb +0 -213
- data/lib/uh/wm/action_handler.rb +0 -77
- data/lib/uh/wm/client.rb +0 -83
- data/lib/uh/wm/manager.rb +0 -84
- data/lib/uh/wm/workers/base_worker.rb +0 -20
- data/lib/uh/wm/workers/blocking_worker.rb +0 -11
- data/lib/uh/wm/workers/multiplexing_worker.rb +0 -33
- data/test/uh/test_wm.rb +0 -36
- data/test/uh/wm/test_client.rb +0 -182
- data/test/uh/wm/test_manager.rb +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fac46367eac28fe3f697da45b08ed7250a5f8ac
|
4
|
+
data.tar.gz: 6d68b1ac9b0627154a98715662a3dd686b4d91b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1009fe21fd3c74988921ae694ea8aff50c953d6777a5ba629dc5a256789aa12b097ec8879099032c4879470bb248dd70dbe9950cf81c146bac9beae2bc951387
|
7
|
+
data.tar.gz: 0ff9b73c6acc2475c794f25e05c01626a20859f74da948af929865062b28512bdd975d6de9b0c41ac59653170c21ee5fd92565d5b96572d7abe8377b5f565bc1
|
data/ext/uh/display.c
CHANGED
@@ -13,8 +13,12 @@ VALUE rdisplay_error_handler = Qnil;
|
|
13
13
|
int display_x_error_handler(Display *dpy, XErrorEvent *e);
|
14
14
|
|
15
15
|
|
16
|
-
VALUE display_s_on_error(VALUE klass
|
17
|
-
|
16
|
+
VALUE display_s_on_error(VALUE klass) {
|
17
|
+
if (!rb_block_given_p()) {
|
18
|
+
rb_raise(rb_eArgError, "no block given");
|
19
|
+
}
|
20
|
+
|
21
|
+
rdisplay_error_handler = rb_block_proc();
|
18
22
|
rb_global_variable(&rdisplay_error_handler);
|
19
23
|
|
20
24
|
return Qnil;
|
data/ext/uh/uh.c
CHANGED
@@ -33,7 +33,7 @@ void uh_color() {
|
|
33
33
|
|
34
34
|
void uh_display() {
|
35
35
|
cDisplay = rb_define_class_under(mUh, "Display", rb_cObject);
|
36
|
-
rb_define_singleton_method(cDisplay, "on_error", display_s_on_error,
|
36
|
+
rb_define_singleton_method(cDisplay, "on_error", display_s_on_error, 0);
|
37
37
|
rb_define_alloc_func(cDisplay, display_alloc);
|
38
38
|
rb_define_attr(cDisplay, "name", 1, 0);
|
39
39
|
rb_define_method(cDisplay, "close", display_close, 0);
|
@@ -120,14 +120,11 @@ void uh_screen() {
|
|
120
120
|
void uh_window() {
|
121
121
|
cWindow = rb_define_class_under(mUh, "Window", rb_cObject);
|
122
122
|
rb_define_attr(cWindow, "id", 1, 0);
|
123
|
-
rb_define_method(cWindow, "destroy", window_destroy, 0);
|
124
123
|
rb_define_method(cWindow, "focus", window_focus, 0);
|
125
124
|
rb_define_method(cWindow, "kill", window_kill, 0);
|
126
125
|
rb_define_method(cWindow, "map", window_map, 0);
|
127
|
-
rb_define_method(cWindow, "mask", window_mask, 0);
|
128
126
|
rb_define_method(cWindow, "mask=", window_mask_set, 1);
|
129
127
|
rb_define_method(cWindow, "name", window_name, 0);
|
130
|
-
rb_define_method(cWindow, "name=", window_name_set, 1);
|
131
128
|
rb_define_method(cWindow, "override_redirect?", window_override_redirect, 0);
|
132
129
|
rb_define_method(cWindow, "raise", window_raise, 0);
|
133
130
|
rb_define_method(cWindow, "unmap", window_unmap, 0);
|
@@ -137,7 +134,6 @@ void uh_window() {
|
|
137
134
|
rb_define_private_method(cWindow, "_configure", window__configure, 4);
|
138
135
|
rb_define_private_method(cWindow, "_configure_event",
|
139
136
|
window__configure_event, 4);
|
140
|
-
rb_define_private_method(cWindow, "_create", window__create, 4);
|
141
137
|
rb_define_private_method(cWindow, "_create_sub", window__create_sub, 4);
|
142
138
|
rb_define_private_method(cWindow, "_moveresize", window__moveresize, 4);
|
143
139
|
}
|
data/ext/uh/uh.h
CHANGED
@@ -47,7 +47,7 @@ VALUE mUh, mEvents,
|
|
47
47
|
|
48
48
|
VALUE color_make(unsigned long pixel);
|
49
49
|
|
50
|
-
VALUE display_s_on_error(VALUE klass
|
50
|
+
VALUE display_s_on_error(VALUE klass);
|
51
51
|
VALUE display_alloc(VALUE klass);
|
52
52
|
VALUE display_close(VALUE self);
|
53
53
|
VALUE display_color_by_name(VALUE self, VALUE rcolor);
|
@@ -80,23 +80,19 @@ VALUE pixmap_make(Display *display, Pixmap xpixmap, VALUE width, VALUE height);
|
|
80
80
|
|
81
81
|
VALUE screen_init(VALUE self, VALUE id, VALUE x, VALUE y, VALUE w, VALUE h);
|
82
82
|
|
83
|
-
VALUE window_destroy(VALUE self);
|
84
83
|
VALUE window_focus(VALUE self);
|
85
84
|
VALUE window_icccm_wm_delete(VALUE self);
|
86
85
|
VALUE window_icccm_wm_protocols(VALUE self);
|
87
86
|
VALUE window_kill(VALUE self);
|
88
87
|
VALUE window_map(VALUE self);
|
89
|
-
VALUE window_mask(VALUE self);
|
90
88
|
VALUE window_mask_set(VALUE self, VALUE mask);
|
91
89
|
VALUE window_name(VALUE self);
|
92
|
-
VALUE window_name_set(VALUE self, VALUE name);
|
93
90
|
VALUE window_override_redirect(VALUE self);
|
94
91
|
VALUE window_raise(VALUE self);
|
95
92
|
VALUE window_unmap(VALUE self);
|
96
93
|
VALUE window_wclass(VALUE self);
|
97
94
|
VALUE window__configure(VALUE self, VALUE rx, VALUE ry, VALUE rw, VALUE rh);
|
98
95
|
VALUE window__configure_event(VALUE self, VALUE rx, VALUE ry, VALUE rw, VALUE rh);
|
99
|
-
VALUE window__create(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h);
|
100
96
|
VALUE window__create_sub(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h);
|
101
97
|
VALUE window__moveresize(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height);
|
102
98
|
int window_id(VALUE window);
|
data/ext/uh/window.c
CHANGED
@@ -9,14 +9,6 @@
|
|
9
9
|
#define WINDOW window->id
|
10
10
|
|
11
11
|
|
12
|
-
VALUE window_destroy(VALUE self) {
|
13
|
-
SET_WINDOW(self);
|
14
|
-
|
15
|
-
XDestroyWindow(DPY, WINDOW);
|
16
|
-
|
17
|
-
return Qnil;
|
18
|
-
}
|
19
|
-
|
20
12
|
VALUE window_focus(VALUE self) {
|
21
13
|
SET_WINDOW(self);
|
22
14
|
|
@@ -76,17 +68,6 @@ VALUE window_map(VALUE self) {
|
|
76
68
|
return Qnil;
|
77
69
|
}
|
78
70
|
|
79
|
-
VALUE window_mask(VALUE self) {
|
80
|
-
XWindowAttributes wa;
|
81
|
-
SET_WINDOW(self);
|
82
|
-
|
83
|
-
if (!XGetWindowAttributes(DPY, WINDOW, &wa)) {
|
84
|
-
rb_raise(rb_eArgError, "cannot get window attributes for `0x%08lx'", WINDOW);
|
85
|
-
}
|
86
|
-
|
87
|
-
return LONG2FIX(wa.your_event_mask);
|
88
|
-
}
|
89
|
-
|
90
71
|
VALUE window_mask_set(VALUE self, VALUE mask) {
|
91
72
|
XSetWindowAttributes attrs;
|
92
73
|
SET_WINDOW(self);
|
@@ -111,14 +92,6 @@ VALUE window_name(VALUE self) {
|
|
111
92
|
return wname;
|
112
93
|
}
|
113
94
|
|
114
|
-
VALUE window_name_set(VALUE self, VALUE name) {
|
115
|
-
SET_WINDOW(self);
|
116
|
-
|
117
|
-
XStoreName(DPY, WINDOW, RSTRING_PTR(name));
|
118
|
-
|
119
|
-
return Qnil;
|
120
|
-
}
|
121
|
-
|
122
95
|
VALUE window_override_redirect(VALUE self) {
|
123
96
|
XWindowAttributes wa;
|
124
97
|
SET_WINDOW(self);
|
@@ -198,18 +171,6 @@ VALUE window__configure_event(VALUE self, VALUE rx, VALUE ry, VALUE rw, VALUE rh
|
|
198
171
|
return Qnil;
|
199
172
|
}
|
200
173
|
|
201
|
-
VALUE window__create(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h) {
|
202
|
-
Window win;
|
203
|
-
SET_WINDOW(self);
|
204
|
-
|
205
|
-
win = XCreateSimpleWindow(DPY, WINDOW,
|
206
|
-
FIX2INT(x), FIX2INT(y), FIX2INT(w), FIX2INT(h),
|
207
|
-
0, BlackPixel(DPY, SCREEN_DEFAULT), BlackPixel(DPY, SCREEN_DEFAULT)
|
208
|
-
);
|
209
|
-
|
210
|
-
return window_make(DPY, win);
|
211
|
-
}
|
212
|
-
|
213
174
|
VALUE window__create_sub(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h) {
|
214
175
|
XSetWindowAttributes wa;
|
215
176
|
Window sub_win;
|
data/lib/uh.rb
CHANGED
data/lib/uh/display.rb
CHANGED
data/lib/uh/version.rb
CHANGED
data/lib/uh/window.rb
CHANGED
data/uh.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibault Jouan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -101,22 +101,11 @@ files:
|
|
101
101
|
- lib/uh/screen.rb
|
102
102
|
- lib/uh/version.rb
|
103
103
|
- lib/uh/window.rb
|
104
|
-
- lib/uh/wm.rb
|
105
|
-
- lib/uh/wm/action_handler.rb
|
106
|
-
- lib/uh/wm/client.rb
|
107
|
-
- lib/uh/wm/manager.rb
|
108
|
-
- lib/uh/wm/workers/base_worker.rb
|
109
|
-
- lib/uh/wm/workers/blocking_worker.rb
|
110
|
-
- lib/uh/wm/workers/multiplexing_worker.rb
|
111
104
|
- test/test_helper.rb
|
112
105
|
- test/uh/test_geo.rb
|
113
|
-
- test/uh/test_wm.rb
|
114
|
-
- test/uh/wm/test_client.rb
|
115
|
-
- test/uh/wm/test_manager.rb
|
116
106
|
- uh.gemspec
|
117
107
|
homepage: https://rubygems.org/gems/uh
|
118
|
-
licenses:
|
119
|
-
- BSD-3-Clause
|
108
|
+
licenses: []
|
120
109
|
metadata: {}
|
121
110
|
post_install_message:
|
122
111
|
rdoc_options: []
|
@@ -129,9 +118,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
118
|
version: '0'
|
130
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
120
|
requirements:
|
132
|
-
- - "
|
121
|
+
- - ">"
|
133
122
|
- !ruby/object:Gem::Version
|
134
|
-
version:
|
123
|
+
version: 1.3.1
|
135
124
|
requirements: []
|
136
125
|
rubyforge_project:
|
137
126
|
rubygems_version: 2.4.5
|
@@ -141,6 +130,4 @@ summary: Xlib simplified toolkit
|
|
141
130
|
test_files:
|
142
131
|
- test/test_helper.rb
|
143
132
|
- test/uh/test_geo.rb
|
144
|
-
|
145
|
-
- test/uh/wm/test_client.rb
|
146
|
-
- test/uh/wm/test_manager.rb
|
133
|
+
has_rdoc:
|
data/lib/uh/wm.rb
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
require 'uh/wm/action_handler'
|
5
|
-
require 'uh/wm/client'
|
6
|
-
require 'uh/wm/manager'
|
7
|
-
require 'uh/wm/workers/base_worker'
|
8
|
-
require 'uh/wm/workers/blocking_worker'
|
9
|
-
require 'uh/wm/workers/multiplexing_worker'
|
10
|
-
|
11
|
-
module Uh
|
12
|
-
class WM
|
13
|
-
include Events
|
14
|
-
|
15
|
-
LOGGER_FORMAT_STR = "%s.%03i %s: %s\n".freeze
|
16
|
-
LOGGER_FORMATER = proc do |severity, datetime, progname, message|
|
17
|
-
LOGGER_FORMAT_STR % [
|
18
|
-
datetime.strftime('%FT%T'),
|
19
|
-
datetime.usec / 1000,
|
20
|
-
severity[0..0],
|
21
|
-
message
|
22
|
-
]
|
23
|
-
end
|
24
|
-
LOGGER_LEVEL = Logger::INFO
|
25
|
-
LOGGER_DEBUG_ENV = 'UH_DEBUG'.freeze
|
26
|
-
|
27
|
-
WORKERS = {
|
28
|
-
blocking: Workers::BlockingWorker,
|
29
|
-
multiplexing: Workers::MultiplexingWorker
|
30
|
-
}.freeze
|
31
|
-
|
32
|
-
DEFAULT_MODIFIER = :mod1
|
33
|
-
INPUT_MASK = SUBSTRUCTURE_REDIRECT_MASK
|
34
|
-
ROOT_MASK = PROPERTY_CHANGE_MASK |
|
35
|
-
SUBSTRUCTURE_REDIRECT_MASK |
|
36
|
-
SUBSTRUCTURE_NOTIFY_MASK |
|
37
|
-
STRUCTURE_NOTIFY_MASK
|
38
|
-
|
39
|
-
extend Forwardable
|
40
|
-
def_delegators :@manager, :on_configure, :on_manage, :on_unmanage,
|
41
|
-
:on_change
|
42
|
-
def_delegator :@logger, :info, :log
|
43
|
-
def_delegator :@logger, :error, :log_error
|
44
|
-
|
45
|
-
attr_reader :actions, :keys, :rules
|
46
|
-
|
47
|
-
def initialize(layout)
|
48
|
-
@layout = layout
|
49
|
-
@display = Display.new
|
50
|
-
@logger = Logger.new($stdout).tap do |o|
|
51
|
-
o.level = ENV.key?(LOGGER_DEBUG_ENV) ? Logger::DEBUG : LOGGER_LEVEL
|
52
|
-
o.formatter = LOGGER_FORMATER
|
53
|
-
end
|
54
|
-
@manager = Manager.new
|
55
|
-
@actions = ActionHandler.new(self, @manager, @layout)
|
56
|
-
@keys = {}
|
57
|
-
@rules = {}
|
58
|
-
end
|
59
|
-
|
60
|
-
def modifier(mod = nil)
|
61
|
-
return (@modifier or DEFAULT_MODIFIER) unless mod
|
62
|
-
@modifier = mod
|
63
|
-
end
|
64
|
-
|
65
|
-
def key(key, mod = nil, &block)
|
66
|
-
mod_mask = KEY_MODIFIERS[modifier]
|
67
|
-
mod_mask |= KEY_MODIFIERS[mod] if mod
|
68
|
-
@keys[[key, mod_mask]] = block
|
69
|
-
end
|
70
|
-
|
71
|
-
def rule(selectors = '', &block)
|
72
|
-
[*selectors].each do |selector|
|
73
|
-
@rules[/\A#{selector}/i] = block
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def on_init(&block)
|
78
|
-
@on_init = block
|
79
|
-
end
|
80
|
-
|
81
|
-
def on_expose(&block)
|
82
|
-
@on_expose = block
|
83
|
-
end
|
84
|
-
|
85
|
-
def worker(*args, **options)
|
86
|
-
@worker = WORKERS[args.first].new(@display, @logger, options)
|
87
|
-
end
|
88
|
-
|
89
|
-
def request_quit!
|
90
|
-
@quit_requested = true
|
91
|
-
end
|
92
|
-
|
93
|
-
def connect
|
94
|
-
@display.open
|
95
|
-
Display.on_error proc { fail OtherWMRunningError }
|
96
|
-
@display.listen_events INPUT_MASK
|
97
|
-
@display.sync false
|
98
|
-
Display.on_error proc { |*args| handle_error(*args) }
|
99
|
-
@display.sync false
|
100
|
-
@display.root.mask = ROOT_MASK
|
101
|
-
@worker.setup
|
102
|
-
@on_init.call @display if @on_init
|
103
|
-
end
|
104
|
-
|
105
|
-
def disconnect
|
106
|
-
@display.close
|
107
|
-
end
|
108
|
-
|
109
|
-
def grab_keys
|
110
|
-
@keys.each do |k, v|
|
111
|
-
key, mod = *k
|
112
|
-
key = key.to_s.gsub /\AXK_/, ''
|
113
|
-
@display.grab_key key, mod
|
114
|
-
end
|
115
|
-
@display.sync false
|
116
|
-
end
|
117
|
-
|
118
|
-
def run_until(&block)
|
119
|
-
@worker.each_event do |e|
|
120
|
-
process_event e
|
121
|
-
break if block.call
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def run
|
126
|
-
run_until { quit_requested? }
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
private
|
131
|
-
|
132
|
-
def modifier_mask(mod)
|
133
|
-
KEY_MODIFIERS[mod]
|
134
|
-
end
|
135
|
-
|
136
|
-
def quit_requested?
|
137
|
-
!!@quit_requested
|
138
|
-
end
|
139
|
-
|
140
|
-
def process_event(event)
|
141
|
-
return unless respond_to? handler = event_handler_method(event), true
|
142
|
-
log_event event
|
143
|
-
send handler, event
|
144
|
-
end
|
145
|
-
|
146
|
-
def event_handler_method(event)
|
147
|
-
('handle_%s' % event.type).to_sym
|
148
|
-
end
|
149
|
-
|
150
|
-
def log_event(event)
|
151
|
-
complement = case event.type
|
152
|
-
when :destroy_notify, :expose, :map_request, :property_notify
|
153
|
-
"window: #{event.window}"
|
154
|
-
when :configure_request
|
155
|
-
'%s, above: #%d, detail: #%d, value_mask: #%d' % [
|
156
|
-
Geo.format_xgeometry(event.x, event.y, event.width, event.height),
|
157
|
-
event.above_window_id,
|
158
|
-
event.detail,
|
159
|
-
event.value_mask
|
160
|
-
]
|
161
|
-
when :key_press
|
162
|
-
"window: #{event.window}, key: #{event.key}, mask: #{event.modifier_mask}"
|
163
|
-
when :unmap_notify
|
164
|
-
"window: #{event.window}, event_window: #{event.event_window}"
|
165
|
-
end
|
166
|
-
|
167
|
-
log [
|
168
|
-
'XEvent', event.type,
|
169
|
-
event.send_event ? 'SENT' : nil,
|
170
|
-
complement
|
171
|
-
].compact.join(' ')
|
172
|
-
end
|
173
|
-
|
174
|
-
def handle_configure_request(event)
|
175
|
-
@manager.configure event.window
|
176
|
-
end
|
177
|
-
|
178
|
-
def handle_destroy_notify(event)
|
179
|
-
@manager.destroy event.window
|
180
|
-
end
|
181
|
-
|
182
|
-
def handle_expose(event)
|
183
|
-
@on_expose.call event.window if @on_expose
|
184
|
-
end
|
185
|
-
|
186
|
-
def handle_key_press(event)
|
187
|
-
actions.call @keys[["XK_#{event.key}".to_sym, event.modifier_mask]]
|
188
|
-
end
|
189
|
-
|
190
|
-
def handle_map_request(event)
|
191
|
-
if client = @manager.map(event.window)
|
192
|
-
@display.listen_events event.window, PROPERTY_CHANGE_MASK
|
193
|
-
@rules.each do |selector, action|
|
194
|
-
if client.wclass =~ selector
|
195
|
-
actions.call action
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def handle_property_notify(event)
|
202
|
-
@manager.update_properties event.window
|
203
|
-
end
|
204
|
-
|
205
|
-
def handle_unmap_notify(event)
|
206
|
-
@manager.unmap event.window
|
207
|
-
end
|
208
|
-
|
209
|
-
def handle_error(req, resource_id, msg)
|
210
|
-
@logger.error "XERROR: #{resource_id} #{req} #{msg}"
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
data/lib/uh/wm/action_handler.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class WM
|
3
|
-
class ActionHandler
|
4
|
-
extend Forwardable
|
5
|
-
def_delegators :@wm, :log, :log_error
|
6
|
-
|
7
|
-
attr_reader :layout
|
8
|
-
|
9
|
-
def initialize(wm, manager, layout)
|
10
|
-
@wm, @manager, @layout = wm, manager, layout
|
11
|
-
end
|
12
|
-
|
13
|
-
def call(action)
|
14
|
-
instance_exec &action
|
15
|
-
rescue LocalJumpError => e
|
16
|
-
log_error "Action: #{e}"
|
17
|
-
end
|
18
|
-
|
19
|
-
def quit
|
20
|
-
log 'Exiting...'
|
21
|
-
@wm.request_quit!
|
22
|
-
end
|
23
|
-
|
24
|
-
def execute(command)
|
25
|
-
log "Spawn `#{command}`"
|
26
|
-
pid = fork do
|
27
|
-
fork do
|
28
|
-
Process.setsid
|
29
|
-
begin
|
30
|
-
exec command
|
31
|
-
rescue Errno::ENOENT => e
|
32
|
-
log_error "Spawn: #{e}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
Process.waitpid pid
|
37
|
-
end
|
38
|
-
|
39
|
-
def log_layout
|
40
|
-
log "Layout:\n#{@layout.to_s.lines.map { |e| " #{e}" }.join.chomp}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def log_clients
|
44
|
-
log "Clients:\n#{@manager.to_s.lines.map { |e| " #{e}" }.join.chomp}"
|
45
|
-
end
|
46
|
-
|
47
|
-
def log_separator
|
48
|
-
log '- ' * 24
|
49
|
-
end
|
50
|
-
|
51
|
-
def method_missing(m, *args, &block)
|
52
|
-
if respond_to? m
|
53
|
-
meth = layout_method m
|
54
|
-
log "#{@layout.class.name}##{meth} #{args.inspect}"
|
55
|
-
begin
|
56
|
-
@layout.send(meth, *args)
|
57
|
-
rescue NoMethodError
|
58
|
-
log_error "Layout does not implement `#{meth}'"
|
59
|
-
end
|
60
|
-
else
|
61
|
-
super
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def respond_to_missing?(m, *)
|
66
|
-
m.to_s =~ /\Alayout_/ || super
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def layout_method(m)
|
73
|
-
m.to_s.gsub(/\Alayout_/, 'handle_').to_sym
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/uh/wm/client.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'uh/geo_accessors'
|
2
|
-
|
3
|
-
module Uh
|
4
|
-
class WM
|
5
|
-
class Client
|
6
|
-
include GeoAccessors
|
7
|
-
|
8
|
-
attr_reader :window
|
9
|
-
attr_accessor :geo, :unmap_count
|
10
|
-
|
11
|
-
def initialize(window)
|
12
|
-
@window = window
|
13
|
-
@hide = true
|
14
|
-
@unmap_count = 0
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
'<%s> (%s) %s win: %s unmaps: %d' %
|
19
|
-
[name, wclass, @geo, @window, @unmap_count]
|
20
|
-
end
|
21
|
-
|
22
|
-
def name
|
23
|
-
@name ||= @window.name
|
24
|
-
end
|
25
|
-
|
26
|
-
def wclass
|
27
|
-
@wclass ||= @window.wclass
|
28
|
-
end
|
29
|
-
|
30
|
-
def hidden?
|
31
|
-
@hide
|
32
|
-
end
|
33
|
-
|
34
|
-
def update_window_properties
|
35
|
-
@name = @window.name
|
36
|
-
@wclass = @window.wclass
|
37
|
-
end
|
38
|
-
|
39
|
-
def configure
|
40
|
-
@window.configure @geo
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
def moveresize
|
45
|
-
@window.moveresize @geo
|
46
|
-
self
|
47
|
-
end
|
48
|
-
|
49
|
-
def show
|
50
|
-
@window.map
|
51
|
-
@hide = false
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
def hide
|
56
|
-
@window.unmap
|
57
|
-
@hide = true
|
58
|
-
@unmap_count += 1
|
59
|
-
self
|
60
|
-
end
|
61
|
-
|
62
|
-
def focus
|
63
|
-
@window.raise
|
64
|
-
@window.focus
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
def kill
|
69
|
-
if @window.icccm_wm_protocols.include? :WM_DELETE_WINDOW
|
70
|
-
@window.icccm_wm_delete
|
71
|
-
else
|
72
|
-
@window.kill
|
73
|
-
end
|
74
|
-
self
|
75
|
-
end
|
76
|
-
|
77
|
-
def kill!
|
78
|
-
@window.kill
|
79
|
-
self
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/lib/uh/wm/manager.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class WM
|
3
|
-
class Manager
|
4
|
-
DEFAULT_GEO = Geo.new(0, 0, 320, 240).freeze
|
5
|
-
|
6
|
-
attr_reader :clients
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@clients = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
@clients.join $/
|
14
|
-
end
|
15
|
-
|
16
|
-
def on_configure(&block)
|
17
|
-
@on_configure = block
|
18
|
-
end
|
19
|
-
|
20
|
-
def on_manage(&block)
|
21
|
-
@on_manage = block
|
22
|
-
end
|
23
|
-
|
24
|
-
def on_unmanage(&block)
|
25
|
-
@on_unmanage = block
|
26
|
-
end
|
27
|
-
|
28
|
-
def on_change(&block)
|
29
|
-
@on_change = block
|
30
|
-
end
|
31
|
-
|
32
|
-
def configure(window)
|
33
|
-
if client = client_for(window)
|
34
|
-
client.configure
|
35
|
-
else
|
36
|
-
geo = @on_configure ? @on_configure.call(window) : DEFAULT_GEO
|
37
|
-
window.configure_event geo
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def map(window)
|
42
|
-
return if window.override_redirect? || client_for(window)
|
43
|
-
Client.new(window).tap { |o| manage o }
|
44
|
-
end
|
45
|
-
|
46
|
-
def unmap(window)
|
47
|
-
return unless client = client_for(window)
|
48
|
-
if client.unmap_count > 0
|
49
|
-
client.unmap_count -= 1
|
50
|
-
else
|
51
|
-
unmanage client
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def destroy(window)
|
56
|
-
return unless client = client_for(window)
|
57
|
-
unmanage client
|
58
|
-
end
|
59
|
-
|
60
|
-
def update_properties(window)
|
61
|
-
return unless client = client_for(window)
|
62
|
-
client.update_window_properties
|
63
|
-
@on_change.call client if @on_change
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def client_for(window)
|
70
|
-
@clients.find { |e| e.window == window }
|
71
|
-
end
|
72
|
-
|
73
|
-
def manage(client)
|
74
|
-
@clients << client
|
75
|
-
@on_manage.call client if @on_manage
|
76
|
-
end
|
77
|
-
|
78
|
-
def unmanage(client)
|
79
|
-
@clients.reject! { |e| e == client }
|
80
|
-
@on_unmanage.call client if @on_unmanage
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class WM
|
3
|
-
module Workers
|
4
|
-
class BaseWorker
|
5
|
-
def initialize(display, logger, **options)
|
6
|
-
@display = display
|
7
|
-
@logger = logger
|
8
|
-
configure **options
|
9
|
-
end
|
10
|
-
|
11
|
-
def configure(**options)
|
12
|
-
end
|
13
|
-
|
14
|
-
def setup
|
15
|
-
self
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class WM
|
3
|
-
module Workers
|
4
|
-
class MultiplexingWorker < BaseWorker
|
5
|
-
DEFAULT_TIMEOUT = 4
|
6
|
-
|
7
|
-
def configure(timeout: DEFAULT_TIMEOUT, on_timeout: nil)
|
8
|
-
@timeout = timeout
|
9
|
-
@on_timeout = on_timeout
|
10
|
-
end
|
11
|
-
|
12
|
-
def setup
|
13
|
-
@display_io = IO.new(@display.fileno)
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
def each_event
|
18
|
-
loop do
|
19
|
-
@display.flush
|
20
|
-
@logger.debug "select [#{@display_io.fileno}], _, _, #{@timeout}"
|
21
|
-
rs, _ = IO.select [@display_io], [], [], @timeout
|
22
|
-
@logger.debug " => #{rs.inspect}"
|
23
|
-
if rs.nil? || rs.empty?
|
24
|
-
@on_timeout.call if @on_timeout
|
25
|
-
else
|
26
|
-
yield @display.next_event while @display.pending?
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/test/uh/test_wm.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'uh/wm'
|
3
|
-
|
4
|
-
module Uh
|
5
|
-
describe WM do
|
6
|
-
subject { WM.new(Object.new) }
|
7
|
-
|
8
|
-
it 'has no rules' do
|
9
|
-
assert_empty subject.rules
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#rule' do
|
13
|
-
let(:block) { proc { } }
|
14
|
-
|
15
|
-
it 'registers a new rule' do
|
16
|
-
subject.rule 'client', &block
|
17
|
-
assert_equal 1, subject.rules.size
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'transforms the given selector as a regexp' do
|
21
|
-
subject.rule 'client', &block
|
22
|
-
assert_equal /\Aclient/i, subject.rules.keys[0]
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'assigns the given block' do
|
26
|
-
subject.rule 'client', &block
|
27
|
-
assert_includes subject.rules.values, block
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'accepts an array of selectors' do
|
31
|
-
subject.rule %w[foo bar], &block
|
32
|
-
assert_equal [/\Afoo/i, /\Abar/i], subject.rules.keys
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/test/uh/wm/test_client.rb
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'test_helper'
|
3
|
-
require 'uh/wm'
|
4
|
-
|
5
|
-
module Uh
|
6
|
-
class WM
|
7
|
-
describe Client do
|
8
|
-
let(:geo) { Geo.new(0, 0, 1024, 768) }
|
9
|
-
let(:window) { OpenStruct.new(name: 'win name', wclass: 'win class') }
|
10
|
-
subject { Client.new(window) }
|
11
|
-
|
12
|
-
before { subject.geo = geo }
|
13
|
-
|
14
|
-
it 'is hidden' do
|
15
|
-
assert subject.hidden?
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'has an unmap count of 0' do
|
19
|
-
assert_equal 0, subject.unmap_count
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '#name' do
|
23
|
-
it 'returns the window name' do
|
24
|
-
assert_equal 'win name', subject.name
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#wclass' do
|
29
|
-
it 'returns the window class' do
|
30
|
-
assert_equal 'win class', subject.wclass
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#update_window_properties' do
|
35
|
-
it 'updates the window name' do
|
36
|
-
window.name = 'new name'
|
37
|
-
assert_equal 'new name', subject.name
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'updates the window class' do
|
41
|
-
window.wclass = 'new class'
|
42
|
-
assert_equal 'new class', subject.wclass
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '#configure' do
|
47
|
-
let(:window) { Minitest::Mock.new }
|
48
|
-
|
49
|
-
before { window.expect :configure, window, [geo] }
|
50
|
-
|
51
|
-
it 'configures the window with client geo' do
|
52
|
-
subject.configure
|
53
|
-
window.verify
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'returns self' do
|
57
|
-
assert_same subject, subject.configure
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '#moveresize' do
|
62
|
-
let(:window) { Minitest::Mock.new }
|
63
|
-
|
64
|
-
before { window.expect :moveresize, window, [geo] }
|
65
|
-
it 'moveresizes the window with client geo' do
|
66
|
-
subject.moveresize
|
67
|
-
window.verify
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'returns self' do
|
71
|
-
assert_same subject, subject.moveresize
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe '#show' do
|
76
|
-
let(:window) { Minitest::Mock.new }
|
77
|
-
|
78
|
-
before { window.expect :map, window }
|
79
|
-
|
80
|
-
it 'maps the window' do
|
81
|
-
subject.show
|
82
|
-
window.verify
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'is not hidden anymore' do
|
86
|
-
subject.show
|
87
|
-
refute subject.hidden?
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'returns self' do
|
91
|
-
assert_same subject, subject.show
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe '#hide' do
|
96
|
-
let(:window) { Minitest::Mock.new }
|
97
|
-
|
98
|
-
before { window.expect :unmap, window }
|
99
|
-
|
100
|
-
it 'unmaps the window' do
|
101
|
-
subject.hide
|
102
|
-
window.verify
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'stays hidden' do
|
106
|
-
subject.hide
|
107
|
-
assert subject.hidden?
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'increments the unmap count' do
|
111
|
-
subject.hide
|
112
|
-
assert_equal 1, subject.unmap_count
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'returns self' do
|
116
|
-
assert_same subject, subject.hide
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
describe '#focus' do
|
121
|
-
let(:window) { Minitest::Mock.new }
|
122
|
-
|
123
|
-
before do
|
124
|
-
window.expect :raise, window
|
125
|
-
window.expect :focus, window
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'raises and focuses the window' do
|
129
|
-
subject.focus
|
130
|
-
window.verify
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'returns self' do
|
134
|
-
assert_same subject, subject.focus
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe '#kill' do
|
139
|
-
let(:window) { Minitest::Mock.new }
|
140
|
-
let(:protocols) { [] }
|
141
|
-
|
142
|
-
before { window.expect :icccm_wm_protocols, protocols }
|
143
|
-
|
144
|
-
it 'kills the window' do
|
145
|
-
window.expect :kill, window
|
146
|
-
subject.kill
|
147
|
-
window.verify
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'returns self' do
|
151
|
-
window.expect :kill, window
|
152
|
-
assert_same subject, subject.kill
|
153
|
-
end
|
154
|
-
|
155
|
-
context 'when window supports icccm wm delete' do
|
156
|
-
let(:protocols) { [:WM_DELETE_WINDOW] }
|
157
|
-
|
158
|
-
it 'icccm deletes the window' do
|
159
|
-
window.expect :icccm_wm_delete, window
|
160
|
-
subject.kill
|
161
|
-
window.verify
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
describe '#kill!' do
|
167
|
-
let(:window) { Minitest::Mock.new }
|
168
|
-
|
169
|
-
before { window.expect :kill, window }
|
170
|
-
|
171
|
-
it 'kills the window' do
|
172
|
-
subject.kill!
|
173
|
-
window.verify
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'returns self' do
|
177
|
-
assert_same subject, subject.kill!
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
data/test/uh/wm/test_manager.rb
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'uh/wm'
|
3
|
-
|
4
|
-
module Uh
|
5
|
-
class WM
|
6
|
-
describe Manager do
|
7
|
-
let(:output) { StringIO.new }
|
8
|
-
let(:window) { Minitest::Mock.new }
|
9
|
-
subject { Manager.new }
|
10
|
-
|
11
|
-
it 'has no clients' do
|
12
|
-
assert subject.clients.empty?
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#configure' do
|
16
|
-
context 'with new window' do
|
17
|
-
it 'sends a default configure event to the window' do
|
18
|
-
window.expect :configure_event, window, [Geo.new(0, 0, 320, 240)]
|
19
|
-
subject.configure window
|
20
|
-
window.verify
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'with a registered callback' do
|
24
|
-
it 'sends configure event with geo returned by callback' do
|
25
|
-
subject.on_configure { Geo.new(0, 0, 42, 42) }
|
26
|
-
window.expect :configure_event, window, [Geo.new(0, 0, 42, 42)]
|
27
|
-
subject.configure window
|
28
|
-
window.verify
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'with known window' do
|
34
|
-
let(:client) { Minitest::Mock.new }
|
35
|
-
|
36
|
-
before do
|
37
|
-
subject.clients << client
|
38
|
-
client.expect :window, window
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'sends a configure message to the client for given window' do
|
42
|
-
window.expect :==, true, [Object]
|
43
|
-
client.expect :configure, client
|
44
|
-
subject.configure window
|
45
|
-
client.verify
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe '#map' do
|
51
|
-
before do
|
52
|
-
window.expect :override_redirect?, false
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'registers a new client' do
|
56
|
-
subject.map window
|
57
|
-
assert_equal 1, subject.clients.size
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'calls the manage callback' do
|
61
|
-
subject.on_manage do |client|
|
62
|
-
assert_equal subject.clients[0], client
|
63
|
-
throw :manage
|
64
|
-
end
|
65
|
-
assert_throws(:manage) { subject.map window }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe '#unmap' do
|
70
|
-
let(:client) { Client.new(window) }
|
71
|
-
|
72
|
-
before do
|
73
|
-
subject.clients << client
|
74
|
-
window.expect :==, true, [Object]
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'when client unmap count is 0 or less' do
|
78
|
-
it 'preserves the unmap count' do
|
79
|
-
subject.unmap window
|
80
|
-
assert_equal 0, client.unmap_count
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'unmanages the client' do
|
84
|
-
subject.unmap window
|
85
|
-
refute_includes subject.clients, client
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'calls the unmanage callback' do
|
89
|
-
subject.on_unmanage do |c|
|
90
|
-
assert_equal client, c
|
91
|
-
throw :unmanage
|
92
|
-
end
|
93
|
-
assert_throws(:unmanage) { subject.unmap window }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
context 'when client unmap count is strictly positive' do
|
98
|
-
before { client.unmap_count += 1 }
|
99
|
-
|
100
|
-
it 'decrements the unmap count' do
|
101
|
-
subject.unmap window
|
102
|
-
assert_equal 0, client.unmap_count
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'does not unmanage the client' do
|
106
|
-
subject.unmap window
|
107
|
-
assert_includes subject.clients, client
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe '#destroy' do
|
113
|
-
let(:client) { Client.new(window) }
|
114
|
-
|
115
|
-
before do
|
116
|
-
subject.clients << client
|
117
|
-
window.expect :==, true, [Object]
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'unmanages the client' do
|
121
|
-
subject.destroy window
|
122
|
-
refute_includes subject.clients, client
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'calls the unmanage callback' do
|
126
|
-
subject.on_unmanage do |c|
|
127
|
-
assert_equal client, c
|
128
|
-
throw :unmanage
|
129
|
-
end
|
130
|
-
assert_throws(:unmanage) { subject.destroy window }
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe '#update_properties' do
|
135
|
-
context 'with known window' do
|
136
|
-
before do
|
137
|
-
window.expect :==, true, [Object]
|
138
|
-
window.expect :name, 'window'
|
139
|
-
window.expect :wclass, 'window class'
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'updates client window properties' do
|
143
|
-
client = Minitest::Mock.new
|
144
|
-
client.expect :window, window
|
145
|
-
subject.clients << client
|
146
|
-
client.expect :update_window_properties, client
|
147
|
-
subject.update_properties window
|
148
|
-
client.verify
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'calls the change callback' do
|
152
|
-
client = Client.new(window)
|
153
|
-
subject.clients << client
|
154
|
-
subject.on_change do |c|
|
155
|
-
assert_same client, c
|
156
|
-
throw :change
|
157
|
-
end
|
158
|
-
assert_throws(:change) { subject.update_properties window }
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|