Fixxes #1272. Using ioctl to get winsize, resizeterm to resize and added the WinChanged action. (#1278)

This commit is contained in:
BDisp
2021-05-03 22:47:25 +01:00
committed by GitHub
parent 71e719fb2b
commit 274b4327a9
4 changed files with 112 additions and 42 deletions

View File

@@ -74,10 +74,10 @@ namespace Terminal.Gui {
public override void Refresh ()
{
Curses.refresh ();
if (Curses.CheckWinChange ()) {
Clip = new Rect (0, 0, Cols, Rows);
TerminalResized?.Invoke ();
}
//if (Curses.CheckWinChange ()) {
// Clip = new Rect (0, 0, Cols, Rows);
// TerminalResized?.Invoke ();
//}
}
public override void UpdateCursor () => Refresh ();
@@ -97,13 +97,13 @@ namespace Terminal.Gui {
//Console.Out.Write ("\x1b[2J");
//Console.Out.Flush ();
// Reports current cursor line and column.
// Set top and bottom lines of a window.
//Console.Out.Write ("\x1b[1;25r");
//Console.Out.Flush ();
//Set cursor key to cursor.
Console.Out.Write("\x1b[?1l");
Console.Out.Flush();
Console.Out.Write ("\x1b[?1l");
Console.Out.Flush ();
}
public override void UpdateScreen () => window.redrawwin ();
@@ -695,6 +695,12 @@ namespace Terminal.Gui {
return true;
});
mLoop.WinChanged += () => {
if (Curses.CheckWinChange ()) {
Clip = new Rect (0, 0, Cols, Rows);
TerminalResized?.Invoke ();
}
};
}
Curses.Event oldMouseEvents, reportableMouseEvents;

View File

@@ -38,6 +38,8 @@ namespace Terminal.Gui {
/// can watch file descriptors using the AddWatch methods.
/// </remarks>
internal class UnixMainLoop : IMainLoopDriver {
public const int KEY_RESIZE = unchecked((int)0xffffffffffffffff);
[StructLayout (LayoutKind.Sequential)]
struct Pollfd {
public int fd;
@@ -84,10 +86,10 @@ namespace Terminal.Gui {
Dictionary<int, Watch> descriptorWatchers = new Dictionary<int, Watch> ();
[DllImport ("libc")]
extern static int poll ([In, Out]Pollfd [] ufds, uint nfds, int timeout);
extern static int poll ([In, Out] Pollfd [] ufds, uint nfds, int timeout);
[DllImport ("libc")]
extern static int pipe ([In, Out]int [] pipes);
extern static int pipe ([In, Out] int [] pipes);
[DllImport ("libc")]
extern static int read (int fd, IntPtr buf, IntPtr n);
@@ -100,13 +102,17 @@ namespace Terminal.Gui {
int [] wakeupPipes = new int [2];
static IntPtr ignore = Marshal.AllocHGlobal (1);
MainLoop mainLoop;
bool winChanged;
public Action WinChanged;
void IMainLoopDriver.Wakeup ()
{
write (wakeupPipes [1], ignore, (IntPtr) 1);
write (wakeupPipes [1], ignore, (IntPtr)1);
}
void IMainLoopDriver.Setup (MainLoop mainLoop) {
void IMainLoopDriver.Setup (MainLoop mainLoop)
{
this.mainLoop = mainLoop;
pipe (wakeupPipes);
AddWatch (wakeupPipes [0], Condition.PollIn, ml => {
@@ -143,7 +149,7 @@ namespace Terminal.Gui {
public object AddWatch (int fileDescriptor, Condition condition, Func<MainLoop, bool> callback)
{
if (callback == null)
throw new ArgumentNullException (nameof(callback));
throw new ArgumentNullException (nameof (callback));
var watch = new Watch () { Condition = condition, Callback = callback, File = fileDescriptor };
descriptorWatchers [fileDescriptor] = watch;
@@ -175,8 +181,11 @@ namespace Terminal.Gui {
UpdatePollMap ();
var n = poll (pollmap, (uint)pollmap.Length, pollTimeout);
return n > 0 || CheckTimers (wait, out pollTimeout);
if (n == KEY_RESIZE) {
winChanged = true;
}
return n >= KEY_RESIZE || CheckTimers (wait, out pollTimeout);
}
bool CheckTimers (bool wait, out int pollTimeout)
@@ -204,6 +213,10 @@ namespace Terminal.Gui {
void IMainLoopDriver.MainIteration ()
{
if (winChanged) {
winChanged = false;
WinChanged?.Invoke ();
}
if (pollmap != null) {
foreach (var p in pollmap) {
Watch watch;

View File

@@ -48,6 +48,14 @@ namespace Unix.Terminal {
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public partial class Curses {
[StructLayout (LayoutKind.Sequential)]
public struct winsize {
public ushort ws_row;
public ushort ws_col;
public ushort ws_xpixel; /* unused */
public ushort ws_ypixel; /* unused */
};
[StructLayout (LayoutKind.Sequential)]
public struct MouseEvent {
public short ID;
@@ -66,8 +74,11 @@ namespace Unix.Terminal {
static NativeMethods methods;
[DllImport("libc")]
public extern static int setlocale(int cate, [MarshalAs(UnmanagedType.LPStr)] string locale);
[DllImport ("libc")]
public extern static int setlocale (int cate, [MarshalAs (UnmanagedType.LPStr)] string locale);
[DllImport ("libc")]
public extern static int ioctl (int fd, int cmd, out winsize argp);
static void LoadMethods ()
{
@@ -86,18 +97,18 @@ namespace Unix.Terminal {
lines_ptr = get_ptr ("LINES");
cols_ptr = get_ptr ("COLS");
}
static public Window initscr ()
{
setlocale(LC_ALL, "");
setlocale (LC_ALL, "");
FindNCurses ();
main_window = new Window (methods.initscr ());
try {
console_sharp_get_dims (out lines, out cols);
} catch (DllNotFoundException){
} catch (DllNotFoundException) {
endwin ();
Console.Error.WriteLine ("Unable to find the @MONO_CURSES@ native library\n" +
Console.Error.WriteLine ("Unable to find the @MONO_CURSES@ native library\n" +
"this is different than the managed mono-curses.dll\n\n" +
"Typically you need to install to a LD_LIBRARY_PATH directory\n" +
"or DYLD_LIBRARY_PATH directory or run /sbin/ldconfig");
@@ -106,7 +117,7 @@ namespace Unix.Terminal {
return main_window;
}
public static int Lines {
public static int Lines {
get {
return lines;
}
@@ -125,16 +136,22 @@ namespace Unix.Terminal {
public static bool CheckWinChange ()
{
int l, c;
console_sharp_get_dims (out l, out c);
if (l != lines || c != cols){
if (l == 1 || l != lines || c != cols) {
lines = l;
cols = c;
if (l <= 0 || c <= 0) {
Console.Out.Write ($"\x1b[8;50;{c}t");
Console.Out.Flush ();
return false;
}
return true;
}
return false;
}
public static int addstr (string format, params object [] args)
{
var s = string.Format (format, args);
@@ -151,9 +168,9 @@ namespace Unix.Terminal {
//
public static int addch (int ch)
{
if (ch < 127 || ch > 0xffff )
if (ch < 127 || ch > 0xffff)
return methods.addch (ch);
char c = (char) ch;
char c = (char)ch;
return addwstr (new String (c, 1));
}
@@ -167,7 +184,7 @@ namespace Unix.Terminal {
throw new Exception ("Could not load the key " + key);
return ptr;
}
internal static IntPtr read_static_ptr (string key)
{
var ptr = get_ptr (key);
@@ -175,8 +192,7 @@ namespace Unix.Terminal {
}
internal static IntPtr console_sharp_get_stdscr () => stdscr;
internal static IntPtr console_sharp_get_curscr ()
{
return Marshal.ReadIntPtr (curscr_ptr);
@@ -184,15 +200,36 @@ namespace Unix.Terminal {
internal static void console_sharp_get_dims (out int lines, out int cols)
{
lines = Marshal.ReadInt32 (lines_ptr);
cols = Marshal.ReadInt32 (cols_ptr);
//lines = Marshal.ReadInt32 (lines_ptr);
//cols = Marshal.ReadInt32 (cols_ptr);
int cmd;
if (UnmanagedLibrary.IsMacOSPlatform) {
cmd = TIOCGWINSZ_MAC;
} else {
cmd = TIOCGWINSZ;
}
if (ioctl (1, cmd, out winsize ws) == 0) {
lines = ws.ws_row;
cols = ws.ws_col;
if (lines == Lines && cols == Cols) {
return;
}
resizeterm (lines, cols);
} else {
lines = Lines;
cols = Cols;
}
}
public static Event mousemask (Event newmask, out Event oldmask)
{
IntPtr e;
var ret = (Event) (methods.mousemask ((IntPtr) newmask, out e));
oldmask = (Event) e;
var ret = (Event)(methods.mousemask ((IntPtr)newmask, out e));
oldmask = (Event)e;
return ret;
}
@@ -210,7 +247,7 @@ namespace Unix.Terminal {
public static bool HasColors => methods.has_colors ();
public static int InitColorPair (short pair, short foreground, short background) => methods.init_pair (pair, foreground, background);
public static int UseDefaultColors () => methods.use_default_colors ();
public static int ColorPairs => methods.COLOR_PAIRS();
public static int ColorPairs => methods.COLOR_PAIRS ();
//
// The proxy methods to call into each version
@@ -240,11 +277,11 @@ namespace Unix.Terminal {
static public int leaveok (IntPtr win, bool bf) => methods.leaveok (win, bf);
static public int wsetscrreg (IntPtr win, int top, int bot) => methods.wsetscrreg (win, top, bot);
static public int scrollok (IntPtr win, bool bf) => methods.scrollok (win, bf);
static public int nl() => methods.nl();
static public int nonl() => methods.nonl();
static public int nl () => methods.nl ();
static public int nonl () => methods.nonl ();
static public int setscrreg (int top, int bot) => methods.setscrreg (top, bot);
static public int refresh () => methods.refresh ();
static public int doupdate() => methods.doupdate();
static public int doupdate () => methods.doupdate ();
static public int wrefresh (IntPtr win) => methods.wrefresh (win);
static public int redrawwin (IntPtr win) => methods.redrawwin (win);
//static public int wredrawwin (IntPtr win, int beg_line, int num_lines) => methods.wredrawwin (win, beg_line, num_lines);
@@ -266,10 +303,13 @@ namespace Unix.Terminal {
static public int start_color () => methods.start_color ();
static public int init_pair (short pair, short f, short b) => methods.init_pair (pair, f, b);
static public int use_default_colors () => methods.use_default_colors ();
static public int COLOR_PAIRS() => methods.COLOR_PAIRS();
static public int COLOR_PAIRS () => methods.COLOR_PAIRS ();
static public uint getmouse (out MouseEvent ev) => methods.getmouse (out ev);
static public uint ungetmouse (ref MouseEvent ev) => methods.ungetmouse (ref ev);
static public int mouseinterval (int interval) => methods.mouseinterval (interval);
static public bool is_term_resized (int lines, int columns) => methods.is_term_resized (lines, columns);
static public int resize_term (int lines, int columns) => methods.resize_term (lines, columns);
static public int resizeterm (int lines, int columns) => methods.resizeterm (lines, columns);
}
#pragma warning disable RCS1102 // Make class static.
@@ -313,7 +353,7 @@ namespace Unix.Terminal {
public delegate int move (int line, int col);
public delegate int curs_set (int visibility);
public delegate int addch (int ch);
public delegate int addwstr([MarshalAs(UnmanagedType.LPWStr)]string s);
public delegate int addwstr ([MarshalAs (UnmanagedType.LPWStr)] string s);
public delegate int wmove (IntPtr win, int line, int col);
public delegate int waddch (IntPtr win, int ch);
public delegate int attron (int attrs);
@@ -332,6 +372,9 @@ namespace Unix.Terminal {
public delegate uint ungetmouse (ref Curses.MouseEvent ev);
public delegate int mouseinterval (int interval);
public delegate IntPtr mousemask (IntPtr newmask, out IntPtr oldMask);
public delegate bool is_term_resized (int lines, int columns);
public delegate int resize_term (int lines, int columns);
public delegate int resizeterm (int lines, int columns);
}
internal class NativeMethods {
@@ -392,6 +435,9 @@ namespace Unix.Terminal {
public readonly Delegates.ungetmouse ungetmouse;
public readonly Delegates.mouseinterval mouseinterval;
public readonly Delegates.mousemask mousemask;
public readonly Delegates.is_term_resized is_term_resized;
public readonly Delegates.resize_term resize_term;
public readonly Delegates.resizeterm resizeterm;
public UnmanagedLibrary UnmanagedLibrary;
public NativeMethods (UnmanagedLibrary lib)
@@ -434,7 +480,7 @@ namespace Unix.Terminal {
wnoutrefresh = lib.GetNativeMethodDelegate<Delegates.wnoutrefresh> ("wnoutrefresh");
move = lib.GetNativeMethodDelegate<Delegates.move> ("move");
curs_set = lib.GetNativeMethodDelegate<Delegates.curs_set> ("curs_set");
addch = lib.GetNativeMethodDelegate<Delegates.addch>("addch");
addch = lib.GetNativeMethodDelegate<Delegates.addch> ("addch");
addwstr = lib.GetNativeMethodDelegate<Delegates.addwstr> ("addwstr");
wmove = lib.GetNativeMethodDelegate<Delegates.wmove> ("wmove");
waddch = lib.GetNativeMethodDelegate<Delegates.waddch> ("waddch");
@@ -454,6 +500,9 @@ namespace Unix.Terminal {
ungetmouse = lib.GetNativeMethodDelegate<Delegates.ungetmouse> ("ungetmouse");
mouseinterval = lib.GetNativeMethodDelegate<Delegates.mouseinterval> ("mouseinterval");
mousemask = lib.GetNativeMethodDelegate<Delegates.mousemask> ("mousemask");
is_term_resized = lib.GetNativeMethodDelegate<Delegates.is_term_resized> ("is_term_resized");
resize_term = lib.GetNativeMethodDelegate<Delegates.resize_term> ("resize_term");
resizeterm = lib.GetNativeMethodDelegate<Delegates.resizeterm> ("resizeterm");
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

View File

@@ -53,6 +53,9 @@ namespace Unix.Terminal {
public const int COLOR_WHITE = unchecked((int)0x7);
public const int KEY_CODE_YES = unchecked((int)0x100);
public const int KEY_CODE_SEQ = unchecked((int)0x5b);
public const int ERR = unchecked((int)0xffffffff);
public const int TIOCGWINSZ = unchecked((int)0x5413);
public const int TIOCGWINSZ_MAC = unchecked((int)0x40087468);
[Flags]
public enum Event : long {
@@ -93,7 +96,6 @@ namespace Unix.Terminal {
public const int DownEnd = unchecked((int)0x0);
public const int Home = unchecked((int)0x0);
#endif
public const int ERR = unchecked((int)0xffffffff);
public const int KeyBackspace = unchecked((int)0x107);
public const int KeyUp = unchecked((int)0x103);
public const int KeyDown = unchecked((int)0x102);