From: William Morgan Date: Thu, 6 Aug 2009 16:21:46 +0000 (-0400) Subject: rewrap getch in select, handle sigwinch manually X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=3478e400ae31b459b2875cc226796a6d4bba11f9;p=sup rewrap getch in select, handle sigwinch manually This is necessary to operate with many versions of the ruby ncurses library, all of which block threads when getch is being called. But this means we can't use getch to determine a sigwich, since we won't see it until an actual key is pressed. so we handle sigwinch ourselves. --- diff --git a/bin/sup b/bin/sup index d52a0ad..2d5de67 100755 --- a/bin/sup +++ b/bin/sup @@ -161,6 +161,7 @@ begin Index.load trap("TERM") { |x| raise "so speaking as i think, i die, i die!" } + trap("WINCH") { |x| BufferManager.sigwinch_happened! } if(s = Redwood::SourceManager.source_for DraftManager.source_name) DraftManager.source = s @@ -228,7 +229,20 @@ begin nil end - next unless c + if c.nil? + if BufferManager.sigwinch_happened? + Redwood::log "redrawing screen on sigwinch" + BufferManager.completely_redraw_screen + end + next + end + + if c == 410 + ## this is ncurses's way of telling us it's detected a refresh. + ## since we have our own sigwinch handler, we don't do anything. + next + end + bm.erase_flash action = begin diff --git a/lib/sup/buffer.rb b/lib/sup/buffer.rb index 7939e27..5881feb 100644 --- a/lib/sup/buffer.rb +++ b/lib/sup/buffer.rb @@ -26,12 +26,13 @@ module Ncurses def sync &b; mutex.synchronize(&b); end def nonblocking_getch - ## INSANITY - ## it is NECESSARY to call nodelay EVERY TIME otherwise a single ctrl-c - ## will turn a blocking call into a nonblocking one. hours of my life - ## wasted on this trivial bullshit: 3. - Ncurses.nodelay Ncurses.stdscr, false - Ncurses.getch + ## INSANTIY + ## it is NECESSARY to wrap Ncurses.getch in a select() otherwise all + ## background threads will be BLOCKED. (except in very modern versions + ## of libncurses-ruby. the current one on ubuntu seems to work well.) + if IO.select([$stdin], nil, nil, 0.5) + c = Ncurses.getch + end end module_function :rows, :cols, :curx, :nonblocking_getch, :mutex, :sync @@ -195,10 +196,15 @@ EOS @flash = nil @shelled = @asking = false @in_x = ENV["TERM"] =~ /(xterm|rxvt|screen)/ + @sigwinch_happened = false + @sigwinch_mutex = Mutex.new self.class.i_am_the_instance self end + def sigwinch_happened!; @sigwinch_mutex.synchronize { @sigwinch_happened = true } end + def sigwinch_happened?; @sigwinch_mutex.synchronize { @sigwinch_happened } end + def buffers; @name_map.to_a; end def focus_on buf @@ -260,6 +266,12 @@ EOS def completely_redraw_screen return if @shelled + ## this magic makes Ncurses get the new size of the screen + Ncurses.endwin + Ncurses.refresh + @sigwinch_mutex.synchronize { @sigwinch_happened = false } + Redwood::log "new screen size is #{Ncurses.rows} x #{Ncurses.cols}" + status, title = get_status_and_title(@focus_buf) # must be called outside of the ncurses lock Ncurses.sync do