uh 1.2.3 → 2.0.0.pre

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d15f9c10043e73d9891e0e63ee0242b979ce6aac
4
- data.tar.gz: bf8dd289b1c4b88f6ea8f9749c14e0b5d6ff7ae2
3
+ metadata.gz: 1fac46367eac28fe3f697da45b08ed7250a5f8ac
4
+ data.tar.gz: 6d68b1ac9b0627154a98715662a3dd686b4d91b7
5
5
  SHA512:
6
- metadata.gz: 3f2d7a2e3f5c157d33d40c69cd8bdec77ab1052241676479606014391925cbcc72c29c5510af874f936bf5769f15b215ca597170761cec2d4b2a59a764fdedb0
7
- data.tar.gz: f13f6fd116766445cb26531b5b5523c0a76f10f122af011a11163d7a83559b21151cfafd90fca81f30aa1aed086241174d7256e1d8c9107ce183dd0a8cda8005
6
+ metadata.gz: 1009fe21fd3c74988921ae694ea8aff50c953d6777a5ba629dc5a256789aa12b097ec8879099032c4879470bb248dd70dbe9950cf81c146bac9beae2bc951387
7
+ data.tar.gz: 0ff9b73c6acc2475c794f25e05c01626a20859f74da948af929865062b28512bdd975d6de9b0c41ac59653170c21ee5fd92565d5b96572d7abe8377b5f565bc1
@@ -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, VALUE handler) {
17
- rdisplay_error_handler = handler;
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;
@@ -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, 1);
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
  }
@@ -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, VALUE handler);
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);
@@ -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
@@ -15,7 +15,6 @@ module Uh
15
15
  Error = Class.new(StandardError)
16
16
  RuntimeError = Class.new(RuntimeError)
17
17
  ArgumentError = Class.new(Error)
18
- OtherWMRunningError = Class.new(RuntimeError)
19
18
 
20
19
  KEY_MODIFIERS = {
21
20
  shift: 1 << 0,
@@ -4,10 +4,6 @@ module Uh
4
4
  ENV['DISPLAY']
5
5
  end
6
6
 
7
- def create_window(geo)
8
- root.create geo
9
- end
10
-
11
7
  def create_subwindow(geo)
12
8
  root.create_sub geo
13
9
  end
@@ -1,3 +1,3 @@
1
1
  module Uh
2
- VERSION = '1.2.3'.freeze
2
+ VERSION = '2.0.0.pre'.freeze
3
3
  end
@@ -18,10 +18,6 @@ module Uh
18
18
  self
19
19
  end
20
20
 
21
- def create(geo)
22
- _create geo.x, geo.y, geo.width, geo.height
23
- end
24
-
25
21
  def create_sub(geo)
26
22
  _create_sub geo.x, geo.y, geo.width, geo.height
27
23
  end
data/uh.gemspec CHANGED
@@ -5,7 +5,6 @@ Gem::Specification.new do |s|
5
5
  s.version = Uh::VERSION.dup
6
6
  s.summary = 'Xlib simplified toolkit'
7
7
  s.description = s.name
8
- s.license = 'BSD-3-Clause'
9
8
  s.homepage = 'https://rubygems.org/gems/uh'
10
9
 
11
10
  s.authors = 'Thibault Jouan'
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: 1.2.3
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-24 00:00:00.000000000 Z
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: '0'
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
- - test/uh/test_wm.rb
145
- - test/uh/wm/test_client.rb
146
- - test/uh/wm/test_manager.rb
133
+ has_rdoc:
@@ -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
@@ -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
@@ -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
@@ -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,11 +0,0 @@
1
- module Uh
2
- class WM
3
- module Workers
4
- class BlockingWorker < BaseWorker
5
- def each_event
6
- @display.each_event { |e| yield e }
7
- end
8
- end
9
- end
10
- end
11
- 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
@@ -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
@@ -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
@@ -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