Skip to content

Commit

Permalink
Fix for cases where the receiver cannot be the owner of the callback
Browse files Browse the repository at this point in the history
Fix #33
* uiTimer
* uiQueueMain
* uiOnShouldQuit
  • Loading branch information
kojix2 committed Nov 18, 2021
1 parent 91e2265 commit ff18a79
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 26 deletions.
3 changes: 1 addition & 2 deletions examples/draw_text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,9 @@ def draw_event(adp, attr_str, font_button, alignment)
handler.DragBroken = do_nothing
handler.KeyEvent = key_event

should_quit = proc do
UI.on_should_quit do
UI.control_destroy(main_window)
end
UI.on_should_quit(should_quit)

@attr_str = make_attribute_string

Expand Down
14 changes: 6 additions & 8 deletions examples/spectrum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,12 @@ def spec
0
end
UI.control_show(main_window)
# FIXME
redraw = Fiddle::Closure::BlockCaller.new(4, [0]) do
UI.area_queue_redraw_all(area)
1
end
timer = proc do
UI.timer(100, redraw)

UI.queue_main do
UI.timer(100) do
UI.area_queue_redraw_all(area)
1
end
end
UI.queue_main(&timer)
UI.main
UI.quit
37 changes: 21 additions & 16 deletions lib/libui/libui_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,29 @@ module LibUIBase

# The proc object is converted to a Closure::BlockCaller object.
args.map!.with_index do |arg, idx|
if arg.is_a?(Proc)
# The types of the function arguments are recorded beforehand.
# See the monkey patch in ffi.rb.
callback = Fiddle::Closure::BlockCaller.new(
*func.callback_argument_types[idx][1..2], &arg
)
# Protect from GC
# See https://github.com/kojix2/LibUI/issues/8
receiver = args[0]
if receiver.instance_variable_defined?(:@callbacks)
receiver.instance_variable_get(:@callbacks) << callback
else
receiver.instance_variable_set(:@callbacks, [callback])
end
callback
next arg unless arg.is_a?(Proc)

# now arg must be Proc

# The types of the function arguments are recorded beforehand.
# See the monkey patch in ffi.rb.
callback = Fiddle::Closure::BlockCaller.new(
*func.callback_argument_types[idx][1..2], &arg
)
# Protect from GC
# by giving the owner object a reference to the callback.
# See https://github.com/kojix2/LibUI/issues/8
owner = if (idx == 0 or owner.frozen?) # e.g. UI.queue_main{}; UI.timer(100) {}
LibUIBase # or UI is better?
else
args[0] # receiver
end
if owner.instance_variable_defined?(:@callbacks)
owner.instance_variable_get(:@callbacks) << callback
else
arg
owner.instance_variable_set(:@callbacks, [callback])
end
callback
end

# Make it possible to omit the last nil. This may be an over-optimization.
Expand Down

0 comments on commit ff18a79

Please sign in to comment.