Ejemplo n.º 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);
     }
 }
Ejemplo n.º 2
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;
			}
		}
Ejemplo n.º 3
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);
            }
        }
Ejemplo n.º 4
0
        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;
        }
Ejemplo n.º 5
0
        private void processLinuxInput(TermKeyKey key)
        {
            // If any special button has been pressed (Tab, Enter, etc)
            // we should convert its code to INPUT_RECORD.KeyEvent
            // Because INPUT_RECORD.KeyEvent depends on Windows' scan codes,
            // we convert codes retrieved from LibTermKey to Windows virtual scan codes
            // In the future, this logic may be changed (for example, both Windows and Linux
            // raw codes can be converted into ConsoleFramework's own abstract enum)
            if (key.type == TermKeyType.TERMKEY_TYPE_KEYSYM) {
                INPUT_RECORD inputRecord = new INPUT_RECORD ();
                inputRecord.EventType = EventType.KEY_EVENT;
                inputRecord.KeyEvent.bKeyDown = true;
                inputRecord.KeyEvent.wRepeatCount = 1;
                switch (key.code.sym) {
                case TermKeySym.TERMKEY_SYM_TAB:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Tab;
                    break;
                case TermKeySym.TERMKEY_SYM_ENTER:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Return;
                    break;
                // in gnome-terminal it is backspace by default
                // (see default compatibility settings in Profile's settings)
                case TermKeySym.TERMKEY_SYM_DEL:
                case TermKeySym.TERMKEY_SYM_BACKSPACE:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Back;
                    break;
                case TermKeySym.TERMKEY_SYM_DELETE:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Delete;
                    break;
                case TermKeySym.TERMKEY_SYM_HOME:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Home;
                    break;
                case TermKeySym.TERMKEY_SYM_END:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.End;
                    break;
                case TermKeySym.TERMKEY_SYM_PAGEUP:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Prior;
                    break;
                case TermKeySym.TERMKEY_SYM_PAGEDOWN:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Next;
                    break;
                case TermKeySym.TERMKEY_SYM_SPACE:
                    inputRecord.KeyEvent.UnicodeChar = ' ';
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Space;
                    break;
                case TermKeySym.TERMKEY_SYM_ESCAPE:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Escape;
                    break;
                case TermKeySym.TERMKEY_SYM_INSERT:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Insert;
                    break;
                case TermKeySym.TERMKEY_SYM_UP:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Up;
                    break;
                case TermKeySym.TERMKEY_SYM_DOWN:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Down;
                    break;
                case TermKeySym.TERMKEY_SYM_LEFT:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Left;
                    break;
                case TermKeySym.TERMKEY_SYM_RIGHT:
                    inputRecord.KeyEvent.wVirtualKeyCode = VirtualKeys.Right;
                    break;
                default:
                    throw new NotSupportedException ("Not supported keyboard code detected: " + key.code.sym);
                }
                inputRecord.KeyEvent.dwControlKeyState = 0;
                if ((key.modifiers & 4) == 4) {
                    inputRecord.KeyEvent.dwControlKeyState |= ControlKeyState.LEFT_CTRL_PRESSED;
                }
                if ((key.modifiers & 2) == 2) {
                    inputRecord.KeyEvent.dwControlKeyState |= ControlKeyState.LEFT_ALT_PRESSED;
                }
                processInputEvent (inputRecord);
            } else if (key.type == TermKeyType.TERMKEY_TYPE_UNICODE) {
                byte[] data = new byte[7];
                data[0] = key.utf8_0;
                data[1] = key.utf8_1;
                data[2] = key.utf8_2;
                data[3] = key.utf8_3;
                data[4] = key.utf8_4;
                data[5] = key.utf8_5;
                data[6] = key.utf8_6;
                string d = System.Text.Encoding.UTF8.GetString(data);
                char unicodeCharacter = d[0];
                INPUT_RECORD inputRecord = new INPUT_RECORD();
                inputRecord.EventType = EventType.KEY_EVENT;
                inputRecord.KeyEvent.bKeyDown = true;
                inputRecord.KeyEvent.wRepeatCount = 1;
                inputRecord.KeyEvent.UnicodeChar = unicodeCharacter;
                inputRecord.KeyEvent.dwControlKeyState = 0;
                if (char.IsLetterOrDigit( unicodeCharacter )) {
                    if (char.IsDigit( unicodeCharacter)) {
                        inputRecord.KeyEvent.wVirtualKeyCode =
                            (VirtualKeys) (unicodeCharacter - '0' + (int) VirtualKeys.N0);
                    } else {
                        char lowercased = char.ToLowerInvariant( unicodeCharacter );

                        // Only english characters can be converted to VirtualKeys
                        if (lowercased >= 'a' && lowercased <= 'z') {
                            inputRecord.KeyEvent.wVirtualKeyCode =
                                (VirtualKeys) (lowercased - 'a' + (int) VirtualKeys.A );
                        }
                    }
                }
                if ((key.modifiers & 4) == 4) {
                    inputRecord.KeyEvent.dwControlKeyState |= ControlKeyState.LEFT_CTRL_PRESSED;
                }
                if ((key.modifiers & 2) == 2) {
                    inputRecord.KeyEvent.dwControlKeyState |= ControlKeyState.LEFT_ALT_PRESSED;
                }
                // todo : remove hardcoded exit combo after testing
                if (unicodeCharacter == 'd' && key.modifiers == 4) {
                    Exit ();
                }
                processInputEvent(inputRecord);
                //
            } else if (key.type == TermKeyType.TERMKEY_TYPE_MOUSE) {
                TermKeyMouseEvent ev;
                int button;
                int line, col;
                LibTermKey.termkey_interpret_mouse(termkeyHandle, ref key, out ev, out button, out line, out col);
                //
                INPUT_RECORD inputRecord = new INPUT_RECORD();
                inputRecord.EventType = EventType.MOUSE_EVENT;
                if (ev == TermKeyMouseEvent.TERMKEY_MOUSE_PRESS || ev == TermKeyMouseEvent.TERMKEY_MOUSE_RELEASE)
                    inputRecord.MouseEvent.dwEventFlags = MouseEventFlags.PRESSED_OR_RELEASED;
                if (ev == TermKeyMouseEvent.TERMKEY_MOUSE_DRAG)
                    inputRecord.MouseEvent.dwEventFlags = MouseEventFlags.MOUSE_MOVED;
                inputRecord.MouseEvent.dwMousePosition = new COORD((short) (col - 1), (short) (line - 1));
                if (ev == TermKeyMouseEvent.TERMKEY_MOUSE_RELEASE) {
                    inputRecord.MouseEvent.dwButtonState = 0;
                } else if (ev == TermKeyMouseEvent.TERMKEY_MOUSE_DRAG || ev == TermKeyMouseEvent.TERMKEY_MOUSE_PRESS) {
                    if (1 == button) {
                        inputRecord.MouseEvent.dwButtonState = MOUSE_BUTTON_STATE.FROM_LEFT_1ST_BUTTON_PRESSED;
                    } else if (2 == button) {
                        inputRecord.MouseEvent.dwButtonState = MOUSE_BUTTON_STATE.FROM_LEFT_2ND_BUTTON_PRESSED;
                    } else if (3 == button) {
                        inputRecord.MouseEvent.dwButtonState = MOUSE_BUTTON_STATE.RIGHTMOST_BUTTON_PRESSED;
                    }
                }
                //
                processInputEvent(inputRecord);
            }
        }
Ejemplo n.º 6
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;
			}
		}