///////////////////////////////////////////////////////////////////////////// // apps/include/graphics/twm4nx/cinput.hxx // Keyboard injection // // Copyright (C) 2019 Gregory Nutt. All rights reserved. // Author: Gregory Nutt // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in // the documentation and/or other materials provided with the // distribution. // 3. Neither the name NuttX nor the names of its contributors may be // used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // ///////////////////////////////////////////////////////////////////////////// #ifndef __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX #define __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX ///////////////////////////////////////////////////////////////////////////// // Included Files ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "graphics/nxwidgets/cnxserver.hxx" ///////////////////////////////////////////////////////////////////////////// // Implementation Classes ///////////////////////////////////////////////////////////////////////////// namespace Twm4Nx { class CTwm4Nx; // Forward reference #ifdef CONFIG_TWM4NX_TOUCHSCREEN /** * Touchscreen calibration data */ #ifdef CONFIG_TWM4NX_TOUCHSCREEN_ANISOTROPIC struct SCalibrationLine { float slope; /**< The slope of a line */ float offset; /**< The offset of a line */ }; struct SCalibrationData { struct SCalibrationLine left; /**< Describes Y values along left edge */ struct SCalibrationLine right; /**< Describes Y values along right edge */ struct SCalibrationLine top; /**< Describes X values along top */ struct SCalibrationLine bottom; /**< Describes X values along bottom edge */ nxgl_coord_t leftX; /**< Left X value used in calibration */ nxgl_coord_t rightX; /**< Right X value used in calibration */ nxgl_coord_t topY; /**< Top Y value used in calibration */ nxgl_coord_t bottomY; /**< Bottom Y value used in calibration */ }; #else struct SCalibrationData { b16_t xSlope; /**< X conversion: xSlope*(x) + xOffset */ b16_t xOffset; b16_t ySlope; /**< Y conversion: ySlope*(y) + yOffset */ b16_t yOffset; }; #endif #endif // CONFIG_TWM4NX_TOUCHSCREEN /** * The CInput class provides receives raw keyboard and mouse inputs and * injects that input into NX which it can be properly distributed to the * window that has focus (i.e., the window at the top of the display * hierarchy, often a modal window). In additional, the cursor is * controlled to track the mouse position. */ class CInput { private: /** * The state of the listener thread. */ enum EListenerState { LISTENER_NOTRUNNING = 0, /**< The listener thread has not yet been started */ LISTENER_STARTED, /**< The listener thread has been started, but is not yet running */ LISTENER_RUNNING, /**< The listener thread is running normally */ LISTENER_STOPREQUESTED, /**< The listener thread has been requested to stop */ LISTENER_TERMINATED, /**< The listener thread terminated normally */ LISTENER_FAILED /**< The listener thread terminated abnormally */ }; /** * CInput state data */ // Session CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */ #ifndef CONFIG_TWM4NX_NOKEYBOARD int m_kbdFd; /**< File descriptor of the opened keyboard device */ #endif #ifndef CONFIG_TWM4NX_NOMOUSE int m_mouseFd; /**< File descriptor of the opened mouse device */ #endif // Listener pthread_t m_thread; /**< The listener thread ID */ volatile enum EListenerState m_state; /**< The state of the listener thread */ sem_t m_waitSem; /**< Used to synchronize with the listener thread */ #ifdef CONFIG_TWM4NX_TOUCHSCREEN // Calibration bool m_calib; /**< False: Use raw, uncalibrated touches */ struct SCalibrationData m_calData; /**< Touchscreen calibration data */ #endif #ifndef CONFIG_TWM4NX_NOKEYBOARD /** * Open the keyboard device. Not very interesting for the case of * standard device but much more interesting for a USB keyboard device * that may disappear when the keyboard is disconnect but later reappear * when the keyboard is reconnected. In this case, this function will * not return until the keyboard device was successfully opened (or * until an irrecoverable error occurs. * * Opens the keyboard device specified by CONFIG_TWM4NX_KEYBOARD_DEVPATH. * * @return On success, then method returns a valid file descriptor. A * negated errno value is returned if an irrecoverable error occurs. */ inline int keyboardOpen(void); #endif #ifndef CONFIG_TWM4NX_NOMOUSE /** * Open the mouse/touchscreen input device. Not very interesting for the * case of standard character device but much more interesting for * USB mouse devices that may disappear when disconnected but later * reappear when reconnected. In this case, this function will * not return until the input device was successfully opened (or * until an irrecoverable error occurs). * * Opens the mouse input device specified by CONFIG_TWM4NX_MOUSE_DEVPATH. * * @return On success, then method returns a valid file descriptor. A * negated errno value is returned if an irrecoverable error occurs. */ inline int mouseOpen(void); #endif #ifndef CONFIG_TWM4NX_NOKEYBOARD /** * Read data from the keyboard device and inject the keyboard data * into NX for proper distribution. * * @return On success, then method returns a valid file descriptor. A * negated errno value is returned if an irrecoverable error occurs. */ inline int keyboardInput(void); #endif #ifndef CONFIG_TWM4NX_NOMOUSE #ifdef CONFIG_TWM4NX_TOUCHSCREEN /** * Calibrate raw touchscreen input. * * @param raw The raw touch sample * @param scaled The location to return the scaled touch position * @return On success, this method returns zero (OK). A negated errno * value is returned if an irrecoverable error occurs. */ int scaleTouchData(FAR const struct touch_point_s &raw, FAR struct nxgl_point_s &scaled); #endif /** * Read data from the mouse/touchscreen device. If the input device * is a mouse, then update the cursor position. And, in either case, * inject the mouse data into NX for proper distribution. * * @return On success, this method returns zero (OK). A negated errno * value is returned if an irrecoverable error occurs. */ inline int mouseInput(void); #endif /** * This is the heart of the keyboard/mouse listener thread. It * contains the actual logic that listeners for and dispatches input * events to the NX server. * * @return If the session terminates gracefully (i.e., because >m_state * is no longer equal to LISTENER_RUNNING, then method returns OK. A * negated errno value is returned if an error occurs while reading from * the input device. A read error, depending upon the type of the * error, may simply indicate that a USB device was removed and we * should wait for the device to be connected. */ inline int session(void); /** * The keyboard/mouse listener thread. This is the entry point of a * thread that listeners for and dispatches keyboard and mouse events * to the NX server. It simply opens the input devices (using * CInput::keyboardOpen() and CInput::mouseOpen()) and executes the * session (via CInput::session()). * * If an errors while reading from the input device AND that device is * configured to use a USB connection, then this function will wait for * the USB device to be re-connected. * * @param arg. The CInput 'this' pointer cast to a void*. * @return This function normally does not return but may return NULL * on error conditions. */ static FAR void *listener(FAR void *arg); public: /** * CInput Constructor * * @param twm4nx. An instance of the Twm4Nx session. */ CInput(CTwm4Nx *twm4nx); /** * CInput Destructor */ ~CInput(void); #ifdef CONFIG_TWM4NX_TOUCHSCREEN /** * Before starting re-calibration, we need to disable touchscreen * calibration and provide raw touchscreen input. Similarly, when * valid touchscreen calibration has been provided via * CInput::setCalibrationData(), then touchscreen processing must * be re-enabled via this method. * * @param enable True will enable calibration. */ inline void enableCalibration(bool enable) { m_calib = enable; } /** * Provide touchscreen calibration data. If calibration data is * received (and the touchscreen is enabled), then received * touchscreen data will be scaled using the calibration data and * forward to the NX layer which dispatches the touchscreen events * in window-relative positions to the correct NX window. * * @param caldata. A reference to the touchscreen data. */ inline void setCalibrationData(const struct SCalibrationData &caldata) { m_calData = caldata; } #endif /** * Start the keyboard/mouse listener thread. * * @return True if the keyboard listener thread was correctly started. */ bool start(void); }; } #endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CINPUT_HXX