Example #1
0
 public static TermKeyResult termkey_getkey_force(IntPtr termKey, ref TermKeyKey key)
 {
     if (IntPtr.Size == 4)
     {
         TermKeyKey32  temp   = new TermKeyKey32();
         TermKeyResult result = termkey_getkey_force32(termKey, ref temp);
         key.type      = temp.type;
         key.code      = temp.code;
         key.modifiers = temp.modifiers;
         key.utf8_0    = temp.utf8_0;
         key.utf8_1    = temp.utf8_1;
         key.utf8_2    = temp.utf8_2;
         key.utf8_3    = temp.utf8_3;
         key.utf8_4    = temp.utf8_4;
         key.utf8_5    = temp.utf8_5;
         key.utf8_6    = temp.utf8_6;
         return(result);
     }
     else
     {
         TermKeyKey64  temp   = new TermKeyKey64();
         TermKeyResult result = termkey_getkey_force64(termKey, ref temp);
         key.type      = temp.type;
         key.code      = temp.code;
         key.modifiers = temp.modifiers;
         key.utf8_0    = temp.utf8_0;
         key.utf8_1    = temp.utf8_1;
         key.utf8_2    = temp.utf8_2;
         key.utf8_3    = temp.utf8_3;
         key.utf8_4    = temp.utf8_4;
         key.utf8_5    = temp.utf8_5;
         key.utf8_6    = temp.utf8_6;
         return(result);
     }
 }
Example #2
0
        public static TermKeyResult termkey_interpret_mouse(IntPtr termKey, ref TermKeyKey key,
                                                            out TermKeyMouseEvent ev,
                                                            out int button,
                                                            out int line,
                                                            out int col)
        {
            if (IntPtr.Size == 4)
            {
                TermKeyKey32 temp = new TermKeyKey32();
                temp.type      = key.type;
                temp.code      = key.code;
                temp.modifiers = key.modifiers;
                temp.utf8_0    = key.utf8_0;
                temp.utf8_1    = key.utf8_1;
                temp.utf8_2    = key.utf8_2;
                temp.utf8_3    = key.utf8_3;
                temp.utf8_4    = key.utf8_4;
                temp.utf8_5    = key.utf8_5;
                temp.utf8_6    = key.utf8_6;

                TermKeyResult result = termkey_interpret_mouse32(termKey, ref temp, out ev, out button, out line, out col);

                key.type      = temp.type;
                key.code      = temp.code;
                key.modifiers = temp.modifiers;
                key.utf8_0    = temp.utf8_0;
                key.utf8_1    = temp.utf8_1;
                key.utf8_2    = temp.utf8_2;
                key.utf8_3    = temp.utf8_3;
                key.utf8_4    = temp.utf8_4;
                key.utf8_5    = temp.utf8_5;
                key.utf8_6    = temp.utf8_6;

                return(result);
            }
            else
            {
                TermKeyKey64 temp = new TermKeyKey64();
                temp.type      = key.type;
                temp.code      = key.code;
                temp.modifiers = key.modifiers;
                temp.utf8_0    = key.utf8_0;
                temp.utf8_1    = key.utf8_1;
                temp.utf8_2    = key.utf8_2;
                temp.utf8_3    = key.utf8_3;
                temp.utf8_4    = key.utf8_4;
                temp.utf8_5    = key.utf8_5;
                temp.utf8_6    = key.utf8_6;

                TermKeyResult result = termkey_interpret_mouse64(termKey, ref temp, out ev, out button, out line, out col);

                key.type      = temp.type;
                key.code      = temp.code;
                key.modifiers = temp.modifiers;
                key.utf8_0    = temp.utf8_0;
                key.utf8_1    = temp.utf8_1;
                key.utf8_2    = temp.utf8_2;
                key.utf8_3    = temp.utf8_3;
                key.utf8_4    = temp.utf8_4;
                key.utf8_5    = temp.utf8_5;
                key.utf8_6    = temp.utf8_6;

                return(result);
            }
        }
        private void runLinux(Control control)
        {
            this.mainControl = control;

            if (userCanvasSize.IsEmpty)
            {
                // Create physical canvas with actual terminal size
                winsize ws = Libc.GetTerminalSize(isDarwin);
                canvas = new PhysicalCanvas(ws.ws_col, ws.ws_row);
            }
            else
            {
                canvas = new PhysicalCanvas(userCanvasSize.Width, userCanvasSize.Height);
            }
            renderer.Canvas          = canvas;
            renderer.RootElementRect = userRootElementRect.IsEmpty
                ? new Rect(canvas.Size) : userRootElementRect;
            renderer.RootElement = mainControl;
            //
            mainControl.Invalidate();

            // Terminal initialization sequence

            // This is magic workaround to avoid messing up terminal after program finish
            // The bug is described at https://bugzilla.xamarin.com/show_bug.cgi?id=15118
            bool ignored = Console.KeyAvailable;

            IntPtr stdscr = NCurses.initscr();

            NCurses.cbreak();
            NCurses.noecho();
            NCurses.nonl();
            NCurses.intrflush(stdscr, false);
            NCurses.keypad(stdscr, true);
            NCurses.start_color();

            HideCursor();
            try {
                renderer.UpdateLayout( );
                renderer.FinallyApplyChangesToCanvas(  );

                termkeyHandle = LibTermKey.termkey_new(0, TermKeyFlag.TERMKEY_FLAG_SPACESYMBOL);

                // Setup the input mode
                Console.Write("\x1B[?1002h");
                pollfd fd = new pollfd( );
                fd.fd     = 0;
                fd.events = POLL_EVENTS.POLLIN;

                pollfd[] fds = new pollfd[2];
                fds[0] = fd;
                fds[1] = new pollfd( );
                int pipeResult = Libc.pipe(pipeFds);
                if (pipeResult == -1)
                {
                    throw new InvalidOperationException("Cannot create self-pipe.");
                }
                fds[1].fd     = pipeFds[0];
                fds[1].events = POLL_EVENTS.POLLIN;

                try {
#if !WIN32
                    // Catch SIGWINCH to handle terminal resizing
                    UnixSignal[] signals = new UnixSignal [] {
                        new UnixSignal(Signum.SIGWINCH)
                    };
                    Thread signal_thread = new Thread(delegate() {
                        while (true)
                        {
                            // Wait for a signal to be delivered
                            int index     = UnixSignal.WaitAny(signals, -1);
                            Signum signal = signals [index].Signum;
                            Libc.writeInt64(pipeFds[1], 2);
                        }
                    }
                                                      );
                    signal_thread.IsBackground = false;
                    signal_thread.Start();
#endif
                    TermKeyKey key = new TermKeyKey( );
                    //
                    this.running      = true;
                    this.mainThreadId = Thread.CurrentThread.ManagedThreadId;
                    //
                    int nextwait = -1;
                    while (true)
                    {
                        int pollRes = Libc.poll(fds, 2, nextwait);
                        if (pollRes == 0)
                        {
                            if (nextwait == -1)
                            {
                                throw new InvalidOperationException("Assertion failed.");
                            }
                            if (TermKeyResult.TERMKEY_RES_KEY == LibTermKey.termkey_getkey_force(termkeyHandle, ref key))
                            {
                                processLinuxInput(key);
                            }
                        }
                        if (pollRes == -1)
                        {
                            int errorCode = Marshal.GetLastWin32Error();
                            if (errorCode != Libc.EINTR)
                            {
                                throw new InvalidOperationException(string.Format("poll() returned with error code {0}", errorCode));
                            }
                        }

                        if (fds[1].revents != POLL_EVENTS.NONE)
                        {
                            UInt64 u;
                            Libc.readInt64(fds[1].fd, out u);
                            if (u == 1)
                            {
                                // Exit from application
#if !WIN32
                                signal_thread.Abort();
#endif
                                break;
                            }
                            if (u == 2)
                            {
                                // Get new term size and process appropriate INPUT_RECORD event
                                INPUT_RECORD inputRecord = new INPUT_RECORD( );
                                inputRecord.EventType = EventType.WINDOW_BUFFER_SIZE_EVENT;

                                winsize ws = Libc.GetTerminalSize(isDarwin);

                                inputRecord.WindowBufferSizeEvent.dwSize.X = ( short )ws.ws_col;
                                inputRecord.WindowBufferSizeEvent.dwSize.Y = ( short )ws.ws_row;
                                processInputEvent(inputRecord);
                            }
                            if (u == 3)
                            {
                                // It is signal from async actions invocation stuff
                            }
                        }

                        if ((fds[0].revents & POLL_EVENTS.POLLIN) == POLL_EVENTS.POLLIN ||
                            (fds[0].revents & POLL_EVENTS.POLLHUP) == POLL_EVENTS.POLLHUP ||
                            (fds[0].revents & POLL_EVENTS.POLLERR) == POLL_EVENTS.POLLERR)
                        {
                            LibTermKey.termkey_advisereadable(termkeyHandle);
                        }

                        TermKeyResult result = (LibTermKey.termkey_getkey(termkeyHandle, ref key));
                        while (result == TermKeyResult.TERMKEY_RES_KEY)
                        {
                            processLinuxInput(key);
                            result = (LibTermKey.termkey_getkey(termkeyHandle, ref key));
                        }

                        if (result == TermKeyResult.TERMKEY_RES_AGAIN)
                        {
                            nextwait = LibTermKey.termkey_get_waittime(termkeyHandle);
                        }
                        else
                        {
                            nextwait = -1;
                        }

                        while (true)
                        {
                            bool anyInvokeActions      = isAnyInvokeActions( );
                            bool anyRoutedEvent        = !EventManager.IsQueueEmpty( );
                            bool anyLayoutToRevalidate = renderer.AnyControlInvalidated;

                            if (!anyInvokeActions && !anyRoutedEvent && !anyLayoutToRevalidate)
                            {
                                break;
                            }

                            EventManager.ProcessEvents();
                            processInvokeActions(  );
                            renderer.UpdateLayout(  );
                        }

                        renderer.FinallyApplyChangesToCanvas( );
                    }
                } finally {
                    LibTermKey.termkey_destroy(termkeyHandle);
                    Libc.close(pipeFds[0]);
                    Libc.close(pipeFds[1]);
                    Console.Write("\x1B[?1002l");
                }
            } finally {
                // Restore cursor visibility before exit
                ShowCursor( );
                NCurses.endwin( );
            }

            renderer.RootElement = null;
        }