commit 3478e400ae31b459b2875cc226796a6d4bba11f9
parent 3b05864b538d3d1c7aa77bc5cc2e4db58f0c9a6d
Author: William Morgan <wmorgan-sup@masanjin.net>
Date: Thu, 6 Aug 2009 12:21:46 -0400
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.
Diffstat:
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git 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
@@ -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