mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-01 08:50:25 +01:00
Fixxes #1272. Using ioctl to get winsize, resizeterm to resize and added the WinChanged action. (#1278)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user