Skip to content

Commit

Permalink
Fixxes gui-cs#1272. Using ioctl to get winsize, resizeterm to resize …
Browse files Browse the repository at this point in the history
…and added the WinChanged action.
  • Loading branch information
BDisp committed May 3, 2021
1 parent 71e719f commit 8c65293
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 42 deletions.
20 changes: 13 additions & 7 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ public override void AddStr (ustring str)
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 ();
Expand All @@ -97,13 +97,13 @@ public override void End ()
//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 ();
Expand Down Expand Up @@ -695,6 +695,12 @@ public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandle
return true;
});

mLoop.WinChanged += () => {
if (Curses.CheckWinChange ()) {
Clip = new Rect (0, 0, Cols, Rows);
TerminalResized?.Invoke ();
}
};
}

Curses.Event oldMouseEvents, reportableMouseEvents;
Expand Down
27 changes: 20 additions & 7 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -84,10 +86,10 @@ class Watch {
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);
Expand All @@ -100,13 +102,17 @@ class Watch {
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 => {
Expand Down Expand Up @@ -143,7 +149,7 @@ public void RemoveWatch (object token)
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;
Expand Down Expand Up @@ -175,8 +181,11 @@ bool IMainLoopDriver.EventsPending (bool wait)
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)
Expand Down Expand Up @@ -204,6 +213,10 @@ bool CheckTimers (bool wait, out int pollTimeout)

void IMainLoopDriver.MainIteration ()
{
if (winChanged) {
winChanged = false;
WinChanged?.Invoke ();
}
if (pollmap != null) {
foreach (var p in pollmap) {
Watch watch;
Expand Down
103 changes: 76 additions & 27 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -66,8 +74,11 @@ public struct MouseEvent {
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 ()
{
Expand All @@ -86,18 +97,18 @@ static void FindNCurses ()
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");
Expand All @@ -106,7 +117,7 @@ static public Window initscr ()
return main_window;
}

public static int Lines {
public static int Lines {
get {
return lines;
}
Expand All @@ -125,16 +136,22 @@ public static int Cols {
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);
Expand All @@ -151,9 +168,9 @@ public static int addstr (string format, params object [] args)
//
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));
}

Expand All @@ -167,32 +184,52 @@ static IntPtr get_ptr (string key)
throw new Exception ("Could not load the key " + key);
return ptr;
}

internal static IntPtr read_static_ptr (string key)
{
var ptr = get_ptr (key);
return Marshal.ReadIntPtr (ptr);
}

internal static IntPtr console_sharp_get_stdscr () => stdscr;



internal static IntPtr console_sharp_get_curscr ()
{
return Marshal.ReadIntPtr (curscr_ptr);
}

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;
}

Expand All @@ -210,7 +247,7 @@ static public int IsAlt (int key)
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
Expand Down Expand Up @@ -240,11 +277,11 @@ static public int IsAlt (int key)
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);
Expand All @@ -266,10 +303,13 @@ static public int IsAlt (int key)
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.
Expand Down Expand Up @@ -313,7 +353,7 @@ internal class Delegates {
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);
Expand All @@ -332,6 +372,9 @@ internal class Delegates {
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 {
Expand Down Expand Up @@ -392,6 +435,9 @@ internal class NativeMethods {
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)
Expand Down Expand Up @@ -434,7 +480,7 @@ public NativeMethods (UnmanagedLibrary lib)
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");
Expand All @@ -454,6 +500,9 @@ public NativeMethods (UnmanagedLibrary lib)
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
Expand Down
4 changes: 3 additions & 1 deletion Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public partial class Curses {
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 {
Expand Down Expand Up @@ -93,7 +96,6 @@ public enum Event : long {
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);
Expand Down

0 comments on commit 8c65293

Please sign in to comment.