private void Run() { _libDevFd = libinput_get_fd(_libInputContext); var timeval = stackalloc IntPtr[2]; foreach (var f in Directory.GetFiles("/dev/input", "event*")) { if (this.Log().IsEnabled(LogLevel.Debug)) { this.Log().Debug($"Opening input device {f}"); } libinput_path_add_device(_libInputContext, f); } while (!_cts.IsCancellationRequested) { IntPtr rawEvent; libinput_dispatch(_libInputContext); while ((rawEvent = libinput_get_event(_libInputContext)) != IntPtr.Zero) { var type = libinput_event_get_type(rawEvent); if (this.Log().IsEnabled(LogLevel.Trace)) { this.Log().Trace($"Got event type (0x{rawEvent:X16}) {type}"); } if (type >= LIBINPUT_EVENT_TOUCH_DOWN && type <= LIBINPUT_EVENT_TOUCH_CANCEL) { ProcessTouchEvent(rawEvent, type); } if (type >= LIBINPUT_EVENT_POINTER_MOTION && type <= LIBINPUT_EVENT_POINTER_AXIS) { ProcessMouseEvent(rawEvent, type); } if (type == LIBINPUT_EVENT_KEYBOARD_KEY) { ProcessKeyboardEvent(rawEvent, type); } libinput_event_destroy(rawEvent); libinput_dispatch(_libInputContext); } var pfd = new pollfd { fd = _libDevFd, events = 1 }; Libc.poll(&pfd, (IntPtr)1, -1); } }
/// <summary> /// Polls a File Descriptor for the passed in flags. /// </summary> /// <param name="fd">The descriptor to poll</param> /// <param name="flags">The flags to poll for</param> /// <param name="timeout">The amount of time to wait; -1 for infinite, 0 for immediate return, and a positive number is the number of milliseconds</param> /// <param name="resultFlags">The flags that were returned by the poll call</param> /// <returns> /// Returns a positive number (which is the number of structures with nonzero revent files), 0 for a timeout or no /// descriptors were ready, or -1 on error. /// </returns> internal unsafe static int poll(int fd, PollFlags flags, int timeout, out PollFlags resultFlags) { pollfd pfd = default(pollfd); pfd.fd = fd; pfd.events = flags; int result = poll(&pfd, 1, timeout); resultFlags = pfd.revents; return(result); }
public static int Poll(this Socket socket, IntPtr ringFd, int timeoutMs) { var pollFds = new pollfd[1]; pollFds[0].fd = ringFd; pollFds[0].events = (short)(PollEvents.POLLIN | PollEvents.POLLPRI); var result = poll(pollFds, (uint)pollFds.Length, timeoutMs); return(result); }
void setupInternalHandles(Span <pollfd> waitHandles, int startIndex) { waitHandles[startIndex] = new pollfd() { fd = pendingQueue.queues.encodedQueueHandle, events = ePollEvents.POLLIN }; waitHandles[startIndex + 1] = new pollfd() { fd = shutdownEvent, events = ePollEvents.POLLIN }; waitHandles[startIndex + 2] = new pollfd() { fd = seekEventHandle, events = ePollEvents.POLLIN }; }
public void Dispose() { _parent._eglDisplay.GlInterface.Flush(); _parent._eglSurface.SwapBuffers(); var nextBo = gbm_surface_lock_front_buffer(_parent._gbmTargetSurface); if (nextBo == IntPtr.Zero) { // Not sure what else can be done Console.WriteLine("gbm_surface_lock_front_buffer failed"); } else { var fb = _parent.GetFbIdForBo(nextBo); bool waitingForFlip = true; drmModePageFlip(_parent._card.Fd, _parent._crtcId, fb, DrmModePageFlip.Event, null); DrmEventPageFlipHandlerDelegate flipCb = (int fd, uint sequence, uint tv_sec, uint tv_usec, void *user_data) => { waitingForFlip = false; }; var cbHandle = GCHandle.Alloc(flipCb); var ctx = new DrmEventContext { version = 4, page_flip_handler = Marshal.GetFunctionPointerForDelegate(flipCb) }; while (waitingForFlip) { var pfd = new pollfd { events = 1, fd = _parent._card.Fd }; poll(&pfd, new IntPtr(1), -1); drmHandleEvent(_parent._card.Fd, &ctx); } cbHandle.Free(); gbm_surface_release_buffer(_parent._gbmTargetSurface, _parent._currentBo); _parent._currentBo = nextBo; } _parent._eglDisplay.ClearContext(); }
private unsafe void InputThread(IntPtr ctx) { var fd = libinput_get_fd(ctx); var timeval = stackalloc IntPtr[2]; foreach (var f in Directory.GetFiles("/dev/input", "event*")) { libinput_path_add_device(ctx, f); } while (true) { IntPtr ev; libinput_dispatch(ctx); while ((ev = libinput_get_event(ctx)) != IntPtr.Zero) { var type = libinput_event_get_type(ev); if (type >= LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN && type <= LibInputEventType.LIBINPUT_EVENT_TOUCH_CANCEL) { HandleTouch(ev, type); } if (type >= LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION && type <= LibInputEventType.LIBINPUT_EVENT_POINTER_AXIS) { HandlePointer(ev, type); } libinput_event_destroy(ev); libinput_dispatch(ctx); } pollfd pfd = new pollfd { fd = fd, events = 1 }; NativeUnsafeMethods.poll(&pfd, new IntPtr(1), 10); } }
public override void Run() { var fds = new pollfd[1]; fds[0].fd = udev_monitor_get_fd(monitor); fds[0].events = pollev.IN; while (true) { int ret = retry(() => poll(fds, (IntPtr)fds.Length, -1)); if (ret == -1) { // FIXME: how do we notify the main program that something bad happened here? break; } var device = udev_monitor_receive_device(monitor); try { var action = udev_device_get_action(device); var syspath = udev_device_get_syspath(device); switch (action) { case "add": if (syspath != null) { paths.Add(syspath); } break; case "remove": paths.Remove(syspath); break; } } finally { udev_device_unref(device); } } }
public static extern int poll(ref pollfd fds, uint nfds, int timeout);
public static extern int poll(ref pollfd fd, uint nfds, int timeout = -1); // < 0 if failed
private static unsafe extern int poll(pollfd* fds, uint count, int timeout);
public static extern int poll(ref pollfd fds, IntPtr nfds, int timeout);
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; }
public static void Main(string[] args) { Thread thread = new Thread(new ThreadStart(() => { Thread.Sleep(TimeSpan.FromSeconds(5)); Console.WriteLine("Message from thread"); int res = LibTermKey.writeInt64(eventfd, 1); Console.WriteLine("write(1) returned {0}\n", res); if (res == -1) { int lastError = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); Console.WriteLine("Last error is {0}\n", lastError); } })); thread.IsBackground = true; thread.Start(); IntPtr handle = LibTermKey.termkey_new(0, TermKeyFlag.TERMKEY_FLAG_SPACESYMBOL); 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(); eventfd = LibTermKey.eventfd(0, EVENTFD_FLAGS.EFD_CLOEXEC); if (eventfd == -1) { Console.WriteLine("Cannot create eventfd\n"); int lastError = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); Console.WriteLine("Last error is {0}\n", lastError); } fds[1].fd = eventfd; fds[1].events = POLL_EVENTS.POLLIN; TermKeyKey key = new TermKeyKey(); while (true) { int pollRes = LibTermKey.poll(fds, 2, -1); if (0 == pollRes) { // timed out Console.WriteLine("Timed out"); if (LibTermKey.termkey_getkey_force(handle, ref key) == TermKeyResult.TERMKEY_RES_KEY) { Console.WriteLine("got TERMKEY_RES_KEY"); } } else if (-1 == pollRes) { int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); Console.WriteLine(string.Format("ErrorCode = {0}", errorCode)); } Console.WriteLine(string.Format("PollRes is {0}", pollRes)); for (int i = 0; i < 2; i++) { if (fds[i].revents != POLL_EVENTS.NONE) { if (i == 1) { UInt64 u; LibTermKey.readInt64(fds[i].fd, out u); Console.WriteLine("Readed eventfd counter : {0}\n", u); } } } 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) { // todo : log return value LibTermKey.termkey_advisereadable(handle); } TermKeyResult result; while ((result = LibTermKey.termkey_getkey(handle, ref key)) == TermKeyResult.TERMKEY_RES_KEY) { Console.WriteLine("Received some key."); string descr = String.Format("Type : {0} Modifiers: {1} Utf8 bytes: {2}{3}{4}{5}{6}{7}{8}", key.type, key.modifiers, key.utf8_0, key.utf8_1, key.utf8_2, key.utf8_3, key.utf8_4, key.utf8_5, key.utf8_6); //dump the retrieved structure //byte[] buffer = new byte[30]; //IntPtr nativeBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(30); //System.Runtime.InteropServices.Marshal.StructureToPtr(key, nativeBuffer, false); //System.Runtime.InteropServices.Marshal.Copy(nativeBuffer, buffer, 0, 30); //for (int i = 0; i < 30; i++ ) { // Console.Write("{0} ", buffer[i]); // if ((i + 1) % 10 == 0) // Console.WriteLine(); //} //System.Runtime.InteropServices.Marshal.FreeHGlobal(nativeBuffer); Console.WriteLine(descr); 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); Console.WriteLine(String.Format("Unicode symbol : {0}", d)); } else if (key.type == TermKeyType.TERMKEY_TYPE_MOUSE) { TermKeyMouseEvent ev; int button; int line, col; LibTermKey.termkey_interpret_mouse(handle, ref key, out ev, out button, out line, out col); Console.WriteLine("MouseEvent : {0} (button {1}) at {2}:{3}", ev, button, line, col); } } } LibTermKey.termkey_destroy(handle); LibTermKey.close(eventfd); }