From 8c194ec17b4fc4810bde451e803d9cb29db28e59 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 14 May 2012 20:46:47 +0000 Subject: NxWM: Calibration is now done on a separate thread; Change mechanism for reporting calibration data; add method to determine if the application is full-screen git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4736 42af7a65-404d-4744-a932-0658087f49c3 --- NxWidgets/ChangeLog.txt | 14 +- NxWidgets/UnitTests/nxwm/main.cxx | 139 +++----- NxWidgets/nxwm/include/capplicationwindow.hxx | 10 + NxWidgets/nxwm/include/ccalibration.hxx | 105 +++++- NxWidgets/nxwm/include/cfullscreenwindow.hxx | 10 + NxWidgets/nxwm/include/cnxconsole.hxx | 10 + NxWidgets/nxwm/include/cstartwindow.hxx | 10 + NxWidgets/nxwm/include/ctouchscreen.hxx | 29 +- NxWidgets/nxwm/include/iapplication.hxx | 10 + NxWidgets/nxwm/include/iapplicationwindow.hxx | 10 + NxWidgets/nxwm/include/nxwmconfig.hxx | 30 ++ NxWidgets/nxwm/src/capplicationwindow.cxx | 13 + NxWidgets/nxwm/src/ccalibration.cxx | 458 +++++++++++++++++++------- NxWidgets/nxwm/src/cfullscreenwindow.cxx | 13 + NxWidgets/nxwm/src/cnxconsole.cxx | 13 + NxWidgets/nxwm/src/cstartwindow.cxx | 13 + NxWidgets/nxwm/src/ctaskbar.cxx | 315 +++++++++++------- NxWidgets/nxwm/src/ctouchscreen.cxx | 8 +- 18 files changed, 866 insertions(+), 344 deletions(-) (limited to 'NxWidgets') diff --git a/NxWidgets/ChangeLog.txt b/NxWidgets/ChangeLog.txt index 0cb95cc13..5b14799bd 100755 --- a/NxWidgets/ChangeLog.txt +++ b/NxWidgets/ChangeLog.txt @@ -70,4 +70,16 @@ a button. Probably should separate basic imaging functionality as CImage and create a new CImageButton. * NxWM::CStartWindow: Now ignores any close application button presses - (You can't close the start window). \ No newline at end of file + (You can't close the start window). +* NxWM::CCalibration: The calibration application now has its own thread. + This was necessary for a proper integration with the taskbar. +* NxWM::CCalibration and NxWM:CTouchscreen: Changed the mechanism use + to report calbration data. It is now reported directly from CCalibration + to CTouchscreen. If external logic needs calibration, it can now get it + from CTouchscreen instead of CCalibration. This change was necessary + to make the termination conditions of CCalibration clean (it used to + have to persist until some external logic got the Calibration data). +* IApplication, IApplicationWindow, and all classes that inherit from + these: Now support method to report if the application is a full-screen + or a normal application. This is necessary to prevent CTaskbar from + displaying a task bar on top of a full-screen window. diff --git a/NxWidgets/UnitTests/nxwm/main.cxx b/NxWidgets/UnitTests/nxwm/main.cxx index 9026a670e..d4b7caa6b 100644 --- a/NxWidgets/UnitTests/nxwm/main.cxx +++ b/NxWidgets/UnitTests/nxwm/main.cxx @@ -428,7 +428,7 @@ static bool createCalibration(void) showTestCaseMemory("After initializing the calibration full screen window"); printf(MAIN_STRING "Creating CCalibration application\n"); - g_nxwmtest.calibration = new NxWM::CCalibration(window, g_nxwmtest.touchscreen); + g_nxwmtest.calibration = new NxWM::CCalibration(g_nxwmtest.taskbar, window, g_nxwmtest.touchscreen); if (!g_nxwmtest.calibration) { printf(MAIN_STRING "ERROR: Failed to instantiate CCalibration\n"); @@ -436,24 +436,22 @@ static bool createCalibration(void) return false; } showTestCaseMemory("After creating CCalibration application"); - return true; -} -#endif -///////////////////////////////////////////////////////////////////////////// -// Name: runCalibration -///////////////////////////////////////////////////////////////////////////// + // Add the calibration application to the start window. It can't really + // be used to re-calibrate (because there is nothing to get the calibration + // data). But is a good case to test a full screen appliation -#ifdef CONFIG_NXWM_TOUCHSCREEN -static bool runCalibration(void) -{ - // 1. Start the calibration application - // 2. Wait until calibration data is available - // 3. Stop the calibration application - // 4. Provide the calibration data to the touchscreen device application - // 5. Enable forwarding of touchscreen input + printf(MAIN_STRING "Adding CCalibration application to the start window\n"); + if (!g_nxwmtest.startwindow->addApplication(g_nxwmtest.calibration)) + { + printf(MAIN_STRING "ERROR: Failed to add CCalibration to the start window\n"); + delete g_nxwmtest.calibration; + return false; + } + showTestCaseMemory("After adding CCalibration application"); - // Call CTaskBar::startApplication to start the Calibration application + // Call CTaskBar::startApplication to start the Calibration application. Nothing + // will be displayed because the window manager has not yet been started. printf(MAIN_STRING "Start the calibration application\n"); if (!g_nxwmtest.taskbar->startApplication(g_nxwmtest.calibration, false)) @@ -462,50 +460,6 @@ static bool runCalibration(void) return false; } showTestCaseMemory("After starting the start window application"); - - // Wait for calibration data - - printf(MAIN_STRING "Get calibration data\n"); - if (!g_nxwmtest.calibration->waitCalibrationData(g_nxwmtest.calibData)) - { - printf(MAIN_STRING "ERROR: Failed to get calibration data\n"); - return false; - } - showTestCaseMemory("After getting calibration data"); - - printf(MAIN_STRING "Stop the calibration application\n"); - if (!g_nxwmtest.taskbar->stopApplication(g_nxwmtest.calibration)) - { - printf(MAIN_STRING "ERROR: Failed to stop the calibration application\n"); - return false; - } - showTestCaseMemory("After stopping the calibration application"); - - // Configure the touchscreen device and enable touch forwarding - - g_nxwmtest.touchscreen->setCalibrationData(g_nxwmtest.calibData); - g_nxwmtest.touchscreen->setEnabled(true); - showTestCaseMemory("After givin calibration dato to the touchscreen device\n"); - return true; -} -#endif - -///////////////////////////////////////////////////////////////////////////// -// Name: addCalibrationToStartWindow -///////////////////////////////////////////////////////////////////////////// - -#ifdef CONFIG_NXWM_TOUCHSCREEN -static bool addCalibrationToStartWindow(void) -{ - printf(MAIN_STRING "Adding CCalibration application to the start window\n"); - if (!g_nxwmtest.startwindow->addApplication(g_nxwmtest.calibration)) - { - printf(MAIN_STRING "ERROR: Failed to add CCalibration to the start window\n"); - delete g_nxwmtest.calibration; - return false; - } - - showTestCaseMemory("After adding CCalibration application"); return true; } #endif @@ -613,6 +567,14 @@ int MAIN_NAME(int argc, char *argv[]) testCleanUpAndExit(EXIT_FAILURE); } + // Create the start window. + + if (!createStartWindow()) + { + printf(MAIN_STRING "ERROR: Failed to create the start window\n"); + testCleanUpAndExit(EXIT_FAILURE); + } + // Create the touchscreen device #ifdef CONFIG_NXWM_TOUCHSCREEN @@ -623,64 +585,55 @@ int MAIN_NAME(int argc, char *argv[]) } #endif - // Perform touchscreen calibration. In a real system, you would only do this - // if you have no saved touchscreen calibration. In this Unit Test, we run - // the calibration unconditionally. + // Create the calibration application and add it to the start window #ifdef CONFIG_NXWM_TOUCHSCREEN - // Create the calibration application - if (!createCalibration()) { printf(MAIN_STRING "ERROR: Failed to create the calibration application\n"); testCleanUpAndExit(EXIT_FAILURE); } +#endif - // Run the touchscreen calibration application + // Create the NxConsole application and add it to the start window - if (!runCalibration()) + if (!createNxConsole()) { - printf(MAIN_STRING "ERROR: Touchscreen Calibration failed\n"); + printf(MAIN_STRING "ERROR: Failed to create the NxConsole application\n"); testCleanUpAndExit(EXIT_FAILURE); } -#endif - - // Create the start window. + // Call CTaskBar::startWindowManager to start the display with applications in place. - if (!createStartWindow()) + if (!startWindowManager()) { - printf(MAIN_STRING "ERROR: Failed to create the start window\n"); + printf(MAIN_STRING "ERROR: Failed to start the window manager\n"); testCleanUpAndExit(EXIT_FAILURE); } #ifdef CONFIG_NXWM_TOUCHSCREEN - // Add the calibration application to the start window. It can't really - // be used to re-calibrate (because there is nothing to get the calibration - // data). But is a good case to test a full screen appliation - - if (!addCalibrationToStartWindow()) - { - printf(MAIN_STRING "ERROR: Failed to add calibration to the start window\n"); - testCleanUpAndExit(EXIT_FAILURE); - } -#endif + // Since we started the touchscreen calibration program maximized, it will run + // immediately when we start the window manager. There is no positive handshake + // to know whenthe touchscreen has been calibrated. If we really want to know, + // we have to poll - // Add the NxConsole application to the start window - - if (!createNxConsole()) + printf(MAIN_STRING "Waiting for touchscreen calibration\n"); + while (!g_nxwmtest.touchscreen->isCalibrated()) { - printf(MAIN_STRING "ERROR: Failed to create the NxConsole application\n"); - testCleanUpAndExit(EXIT_FAILURE); + std::sleep(2); } - // Call CTaskBar::startWindowManager to start the display with applications in place. + // This is how we would then recover the calibration data. After the calibration + // application creates the calibration data, it hands it to the touchscreen driver + // After the touchscreen driver gets it, it will report isCalibrated() == true + // and then we can read the calibration data from the touchscreen driver. - if (!startWindowManager()) + printf(MAIN_STRING "Getting calibration data from the touchscreen\n"); + if (!g_nxwmtest.touchscreen->getCalibrationData(g_nxwmtest.calibData)) { - printf(MAIN_STRING "ERROR: Failed to start the window manager\n"); - testCleanUpAndExit(EXIT_FAILURE); - } + printf(MAIN_STRING "ERROR: Failed to get calibration data from the touchscreen\n"); + } +#endif // Wait a little bit for the display to stabilize. The simulation pressing of // the 'start window' icon in the task bar diff --git a/NxWidgets/nxwm/include/capplicationwindow.hxx b/NxWidgets/nxwm/include/capplicationwindow.hxx index 807f268a6..1a3d7eb48 100644 --- a/NxWidgets/nxwm/include/capplicationwindow.hxx +++ b/NxWidgets/nxwm/include/capplicationwindow.hxx @@ -158,6 +158,16 @@ namespace NxWM void setWindowLabel(NXWidgets::CNxString &appname); + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + bool isFullScreen(void) const; + /** * Register to receive callbacks when toolbar icons are selected */ diff --git a/NxWidgets/nxwm/include/ccalibration.hxx b/NxWidgets/nxwm/include/ccalibration.hxx index 535a14804..3d90d59a8 100644 --- a/NxWidgets/nxwm/include/ccalibration.hxx +++ b/NxWidgets/nxwm/include/ccalibration.hxx @@ -42,12 +42,14 @@ #include +#include #include #include "cnxstring.hxx" #include "cwidgeteventhandler.hxx" #include "cwidgetcontrol.hxx" +#include "ctaskbar.hxx" #include "iapplication.hxx" #include "cfullscreenwindow.hxx" @@ -97,18 +99,33 @@ namespace NxWM class CCalibration : public IApplication { private: + /** + * The state of the calibration thread. + */ + + enum ECalThreadState + { + CALTHREAD_NOTRUNNING = 0, /**< The calibration thread has not yet been started */ + CALTHREAD_STARTED, /**< The calibration thread has been started, but is not yet running */ + CALTHREAD_RUNNING, /**< The calibration thread is running normally */ + CALTHREAD_STOPREQUESTED, /**< The calibration thread has been requested to stop */ + CALTHREAD_HIDE, /**< The hide() called by calibration thread running */ + CALTHREAD_SHOW, /**< The redraw() called by calibration thread running */ + CALTHREAD_TERMINATED /**< The calibration thread terminated normally */ + }; + /** * Identifies the current display state */ - enum ECalibState + enum ECalibrationPhase { - CALIB_NOT_STARTED = 0, /**< Constructed, but not yet started */ - CALIB_UPPER_LEFT, /**< Touch point is in the upper left corner */ - CALIB_UPPER_RIGHT, /**< Touch point is in the upper right corner */ - CALIB_LOWER_RIGHT, /**< Touch point is in the lower left corner */ - CALIB_LOWER_LEFT, /**< Touch point is in the lower right corner */ - CALIB_COMPLETE /**< Calibration is complete */ + CALPHASE_NOT_STARTED = 0, /**< Constructed, but not yet started */ + CALPHASE_UPPER_LEFT, /**< Touch point is in the upper left corner */ + CALPHASE_UPPER_RIGHT, /**< Touch point is in the upper right corner */ + CALPHASE_LOWER_RIGHT, /**< Touch point is in the lower left corner */ + CALPHASE_LOWER_LEFT, /**< Touch point is in the lower right corner */ + CALPHASE_COMPLETE /**< Calibration is complete */ }; /** @@ -126,15 +143,17 @@ namespace NxWM * CCalibration state data */ + CTaskbar *m_taskbar; /**< The taskbar (used to terminate calibration) */ CFullScreenWindow *m_window; /**< The window for the calibration display */ CTouchscreen *m_touchscreen; /**< The touchscreen device */ - enum ECalibState m_state; /**< Current calibration display state */ + pthread_t m_thread; /**< The calibration thread ID */ struct SCalibScreenInfo m_screenInfo; /**< Describes the current calibration display */ struct nxgl_point_s m_touchPos; /**< This is the last touch position */ + volatile uint8_t m_calthread; /**< Current calibration display state (See ECalibThreadState)*/ + uint8_t m_calphase; /**< Current calibration display state (See ECalibrationPhase)*/ bool m_stop; /**< True: We have been asked to stop the calibration */ bool m_touched; /**< True: The screen is touched */ uint8_t m_touchId; /**< The ID of the touch */ - sem_t m_waitSem; /**< Supports wait for calibration data */ struct nxgl_point_s m_calibData[CALIB_DATA_POINTS]; /** @@ -145,6 +164,42 @@ namespace NxWM void touchscreenInput(struct touch_sample_s &sample); + /** + * Start the calibration thread. + * + * @param initialState. The initial state of the calibration thread + * @return True if the thread was successfully started. + */ + + bool startCalibration(enum ECalThreadState initialState); + + /** + * Return true if the calibration thread is running normally. There are + * lots of potential race conditions. Let's hope that things are running + * orderly and we that we do not have to concern ourself with them + * + * @return True if the calibration thread is runnning normally. + */ + + inline bool isRunning(void) const + { + // What if the boundary states CALTHREAD_STARTED and CALTHREAD_STOPREQUESTED? + + return (m_calthread == CALTHREAD_RUNNING || + m_calthread == CALTHREAD_HIDE || + m_calthread == CALTHREAD_SHOW); + } + + /** + * The calibration thread. This is the entry point of a thread that provides the + * calibration displays, waits for input, and collects calibration data. + * + * @param arg. The CCalibration 'this' pointer cast to a void*. + * @return This function always returns NULL when the thread exits + */ + + static FAR void *calibration(FAR void *arg); + /** * This is the calibration state machine. It is called initially and then * as new touchscreen data is received. @@ -158,16 +213,36 @@ namespace NxWM void showCalibration(void); + /** + * Finish calibration steps and provide the calibration data to the + * touchscreen driver. + */ + + void finishCalibration(void); + + /** + * Given the raw touch data collected by the calibration thread, create the + * massaged calibration data needed by CTouchscreen. + * + * @param data. A reference to the location to save the calibration data + * @return True if the calibration data was successfully created. + */ + + bool createCalibrationData(struct SCalibrationData &data); + public: /** * CCalibration Constructor * + * @param taskbar. The taskbar instance used to terminate calibration * @param window. The window to use for the calibration display - * @param touchscreen. An instance of the class that wraps the touchscreen device. + * @param touchscreen. An instance of the class that wraps the + * touchscreen device. */ - CCalibration(CFullScreenWindow *window, CTouchscreen *touchscreen); + CCalibration(CTaskbar *taskbar, CFullScreenWindow *window, + CTouchscreen *touchscreen); /** * CCalibration Destructor @@ -230,12 +305,14 @@ namespace NxWM void redraw(void); /** - * Wait for calibration data to be received. + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. * - * @return True if the calibration data was successfully obtained. + * @return True if this is a full screen window. */ - bool waitCalibrationData(struct SCalibrationData &data); + bool isFullScreen(void) const; }; } diff --git a/NxWidgets/nxwm/include/cfullscreenwindow.hxx b/NxWidgets/nxwm/include/cfullscreenwindow.hxx index fb4788830..3c4117689 100644 --- a/NxWidgets/nxwm/include/cfullscreenwindow.hxx +++ b/NxWidgets/nxwm/include/cfullscreenwindow.hxx @@ -122,6 +122,16 @@ namespace NxWM void setWindowLabel(NXWidgets::CNxString &appname); + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + bool isFullScreen(void) const; + /** * Register to receive callbacks when toolbar icons are selected */ diff --git a/NxWidgets/nxwm/include/cnxconsole.hxx b/NxWidgets/nxwm/include/cnxconsole.hxx index 1c7aab193..426cf165f 100644 --- a/NxWidgets/nxwm/include/cnxconsole.hxx +++ b/NxWidgets/nxwm/include/cnxconsole.hxx @@ -173,6 +173,16 @@ namespace NxWM */ void redraw(void); + + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + bool isFullScreen(void) const; }; } #endif // __cplusplus diff --git a/NxWidgets/nxwm/include/cstartwindow.hxx b/NxWidgets/nxwm/include/cstartwindow.hxx index a04a4f1a5..5a5ea12f4 100644 --- a/NxWidgets/nxwm/include/cstartwindow.hxx +++ b/NxWidgets/nxwm/include/cstartwindow.hxx @@ -188,6 +188,16 @@ namespace NxWM void redraw(void); + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + bool isFullScreen(void) const; + /** * Add the application to the start window. The general sequence for * setting up the start window is: diff --git a/NxWidgets/nxwm/include/ctouchscreen.hxx b/NxWidgets/nxwm/include/ctouchscreen.hxx index 52433c1de..396400204 100644 --- a/NxWidgets/nxwm/include/ctouchscreen.hxx +++ b/NxWidgets/nxwm/include/ctouchscreen.hxx @@ -166,6 +166,17 @@ namespace NxWM m_enabled = enable; } + /** + * Is the touchscreen calibrated? + * + * @return True if the touchscreen has been calibrated. + */ + + inline bool isCalibrated(void) const + { + return m_calibrated; + } + /** * Provide touchscreen calibration data. If calibration data is received (and * the touchscreen is enabled), then received touchscreen data will be scaled @@ -175,7 +186,23 @@ namespace NxWM * @param data. A reference to the touchscreen data. */ - void setCalibrationData(struct SCalibrationData &caldata); + void setCalibrationData(const struct SCalibrationData &caldata); + + /** + * Recover the calibration data so that it can be saved to non-volatile storage. + * + * @param data. A reference to the touchscreen data. + * @return True if calibration data was successfully returned. + */ + + inline bool getCalibrationData(struct SCalibrationData &caldata) const + { + if (m_calibrated) + { + caldata = m_calibData; + } + return m_calibrated; + } /** * Capture raw driver data. This method will capture mode one raw touchscreen diff --git a/NxWidgets/nxwm/include/iapplication.hxx b/NxWidgets/nxwm/include/iapplication.hxx index e92e1908e..0d33db7bc 100644 --- a/NxWidgets/nxwm/include/iapplication.hxx +++ b/NxWidgets/nxwm/include/iapplication.hxx @@ -170,6 +170,16 @@ namespace NxWM { return m_topapp; } + + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + virtual bool isFullScreen(void) const = 0; }; } diff --git a/NxWidgets/nxwm/include/iapplicationwindow.hxx b/NxWidgets/nxwm/include/iapplicationwindow.hxx index 115998775..b00a03fa2 100644 --- a/NxWidgets/nxwm/include/iapplicationwindow.hxx +++ b/NxWidgets/nxwm/include/iapplicationwindow.hxx @@ -129,6 +129,16 @@ namespace NxWM virtual void setWindowLabel(NXWidgets::CNxString &appname) = 0; + /** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + + virtual bool isFullScreen(void) const = 0; + /** * Register to receive callbacks when toolbar icons are selected */ diff --git a/NxWidgets/nxwm/include/nxwmconfig.hxx b/NxWidgets/nxwm/include/nxwmconfig.hxx index 359f7d095..88c2ea8db 100644 --- a/NxWidgets/nxwm/include/nxwmconfig.hxx +++ b/NxWidgets/nxwm/include/nxwmconfig.hxx @@ -333,6 +333,10 @@ * Default: "/dev/input0" * CONFIG_NXWM_TOUCHSCREEN_SIGNO - The realtime signal used to wake up the * touchscreen listener thread. Default: 5 + * CONFIG_NXWM_TOUCHSCREEN_LISTENERPRIO - Priority of the touchscreen listener + * thread. Default: SCHED_PRIORITY_DEFAULT + * CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK - Touchscreen listener thread stack + * size. Default 2048 */ #ifndef CONFIG_NXWM_TOUCHSCREEN_DEVNO @@ -347,6 +351,14 @@ # define CONFIG_NXWM_TOUCHSCREEN_SIGNO 5 #endif +#ifndef CONFIG_NXWM_TOUCHSCREEN_LISTENERPRIO +# define CONFIG_NXWM_TOUCHSCREEN_LISTENERPRIO SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK +# define CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK 2048 +#endif + /* Calibration display ******************************************************/ /** * Calibration display settings: @@ -363,6 +375,12 @@ * MKRGB(255, 255, 96) (very light yellow) * CONFIG_NXWM_CALIBRATION_ICON - The ICON to use for the touchscreen * calibration application. Default: NxWM::g_calibrationBitmap + * CONFIG_NXWM_CALIBRATION_SIGNO - The realtime signal used to wake up the + * touchscreen calibration thread. Default: 5 + * CONFIG_NXWM_CALIBRATION_LISTENERPRIO - Priority of the touchscreen listener + * thread. Default: SCHED_PRIORITY_DEFAULT + * CONFIG_NXWM_CALIBRATION_LISTENERSTACK - Touchscreen listener thread stack + * size. Default 2048 */ #ifndef CONFIG_NXWM_CALIBRATION_BACKGROUNDCOLOR @@ -385,6 +403,18 @@ # define CONFIG_NXWM_CALIBRATION_ICON NxWM::g_calibrationBitmap #endif +#ifndef CONFIG_NXWM_CALIBRATION_SIGNO +# define CONFIG_NXWM_CALIBRATION_SIGNO 5 +#endif + +#ifndef CONFIG_NXWM_CALIBRATION_LISTENERPRIO +# define CONFIG_NXWM_CALIBRATION_LISTENERPRIO SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_NXWM_CALIBRATION_LISTENERSTACK +# define CONFIG_NXWM_CALIBRATION_LISTENERSTACK 2048 +#endif + /**************************************************************************** * Global Function Prototypes ****************************************************************************/ diff --git a/NxWidgets/nxwm/src/capplicationwindow.cxx b/NxWidgets/nxwm/src/capplicationwindow.cxx index d2190cd24..60ab5a3d3 100644 --- a/NxWidgets/nxwm/src/capplicationwindow.cxx +++ b/NxWidgets/nxwm/src/capplicationwindow.cxx @@ -424,6 +424,19 @@ void CApplicationWindow::setWindowLabel(NXWidgets::CNxString &appname) m_windowLabel->setText(appname); } +/** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + +bool CApplicationWindow::isFullScreen(void) const +{ + return false; +} + /** * Register to receive callbacks when toolbar icons are selected */ diff --git a/NxWidgets/nxwm/src/ccalibration.cxx b/NxWidgets/nxwm/src/ccalibration.cxx index 1fc9f3466..2f9adb2e0 100644 --- a/NxWidgets/nxwm/src/ccalibration.cxx +++ b/NxWidgets/nxwm/src/ccalibration.cxx @@ -37,8 +37,11 @@ * Included Files ****************************************************************************/ +#include +#include + +#include #include -#include #include #include "nxwmconfig.hxx" @@ -78,18 +81,23 @@ using namespace NxWM; /** * CCalibration Constructor * + * @param taskbar. The taskbar instance used to terminate calibration * @param window. The window to use for the calibration display - * @param touchscreen. An instance of the class that wraps the touchscreen device. + * @param touchscreen. An instance of the class that wraps the touchscreen + * device. */ -CCalibration::CCalibration(CFullScreenWindow *window, CTouchscreen *touchscreen) +CCalibration::CCalibration(CTaskbar *taskbar, CFullScreenWindow *window, + CTouchscreen *touchscreen) { // Initialize state data + m_taskbar = taskbar; m_window = window; m_touchscreen = touchscreen; - m_state = CALIB_NOT_STARTED; - m_stop = false; + m_thread = 0; + m_calthread = CALTHREAD_NOTRUNNING; + m_calphase = CALPHASE_NOT_STARTED; m_touched = false; } @@ -150,27 +158,9 @@ NXWidgets::CNxString CCalibration::getName(void) bool CCalibration::run(void) { - // Provide the initial display - - m_state = CALIB_NOT_STARTED; - stateMachine(); - - // Loop until calibration completes - - while (!m_stop && m_state != CALIB_COMPLETE) - { - // Wait for the next raw touchscreen input - - struct touch_sample_s sample; - while (!m_touchscreen->waitRawTouchData(&sample)); + gvdbg("Starting calibration: m_calthread=%d\n", (int)m_calthread); - // Then process the raw touchscreen input - - touchscreenInput(sample); - } - - m_stop = false; - return true; + return startCalibration(CALTHREAD_STARTED); } /** @@ -179,10 +169,29 @@ bool CCalibration::run(void) void CCalibration::stop(void) { - // The main thread is stuck waiting for the next touchscreen input... - // So this is probably just a waste of good FLASH space. + gvdbg("Stopping calibration: m_calthread=%d\n", (int)m_calthread); + + // Was the calibration thread created? + + if (m_thread != 0) + { + // Is the calibration thread running? + + if (isRunning()) + { + // The main thread is stuck waiting for the next touchscreen input... + // We can signal that we would like the thread to stop, but we will be + // stuck here until the next touch - m_stop = true; + m_calthread = CALTHREAD_STOPREQUESTED; + + // Try to wake up the calibration thread so that it will see our + // terminatin request + + gvdbg("Stopping calibration: m_calthread=%d\n", (int)m_calthread); + (void)pthread_kill(m_thread, CONFIG_NXWM_CALIBRATION_SIGNO); + } + } } /** @@ -192,7 +201,17 @@ void CCalibration::stop(void) void CCalibration::hide(void) { - // REVISIT + gvdbg("Entry\n"); + + // Is the calibration thread running? + + if (m_calthread == CALTHREAD_RUNNING || m_calthread == CALTHREAD_SHOW) + { + // Ask the calibration thread to hide the display + + m_calthread = CALTHREAD_HIDE; + (void)pthread_kill(m_thread, CONFIG_NXWM_CALIBRATION_SIGNO); + } } /** @@ -203,89 +222,43 @@ void CCalibration::hide(void) void CCalibration::redraw(void) { - // Reset the state machine and start over + gvdbg("Entry\n"); - if (m_state != CALIB_COMPLETE) - { - m_state = CALIB_NOT_STARTED; - stateMachine(); - } -} - -/** - * Wait for calibration data to be received. - * - * @return True if the calibration data was successfully obtained. - */ + // Is the calibration thread running? We might have to restart it if + // we have completed the calibration early but are being brought to + // top of the display again -bool CCalibration::waitCalibrationData(struct SCalibrationData &data) -{ - // Wait until calibration is finished + // Is the calibration thread running? - while (m_state != CALIB_COMPLETE) + if (!isRunning()) { -#ifdef CONFIG_DEBUG - int ret = sem_wait(&m_waitSem); - DEBUGASSERT(ret == 0 || errno == EINTR); -#else - (void)sem_wait(&m_waitSem); -#endif + gvdbg("Starting calibration: m_calthread=%d\n", (int)m_calthread); + (void)startCalibration(CALTHREAD_SHOW); } - // Recover the window instance contained in the full screen window - - NXWidgets::INxWindow *window = m_window->getWindow(); - - // Get the size of the fullscreen window + // The calibration thread is running. Make sure that is is not + // already processing a redraw - struct nxgl_size_s windowSize; - if (!window->getSize(&windowSize)) + else if (m_calthread != CALTHREAD_SHOW) { - return false; - } - - // Calculate the calibration parameters - // - // (scaledX - LEFTX) / (rawX - leftX) = (RIGHTX - LEFTX) / (rightX - leftX) - // scaledX = (rawX - leftX) * (RIGHTX - LEFTX) / (rightX - leftX) + LEFTX - // = rawX * xSlope + (LEFTX - leftX * xSlope) - // = rawX * xSlope + xOffset - // - // where: - // xSlope = (RIGHTX - LEFTX) / (rightX - leftX) - // xOffset = (LEFTX - leftX * xSlope) + // Ask the calibration thread to restart the calibration and redraw the display - b16_t leftX = (m_calibData[CALIB_UPPER_LEFT_INDEX].x + - m_calibData[CALIB_LOWER_LEFT_INDEX].x) << 15; - b16_t rightX = (m_calibData[CALIB_UPPER_RIGHT_INDEX].x + - m_calibData[CALIB_LOWER_RIGHT_INDEX].x) << 15; - - data.xSlope = b16divb16(itob16(CALIBRATION_RIGHTX - CALIBRATION_LEFTX), (rightX - leftX)); - data.xOffset = itob16(CALIBRATION_LEFTX) - b16mulb16(leftX, data.xSlope); - - gdbg("New xSlope: %08x xOffset: %08x\n", data.xSlope, data.xOffset); - - // Similarly for Y - // - // (scaledY - TOPY) / (rawY - topY) = (BOTTOMY - TOPY) / (bottomY - topY) - // scaledY = (rawY - topY) * (BOTTOMY - TOPY) / (bottomY - topY) + TOPY - // = rawY * ySlope + (TOPY - topY * ySlope) - // = rawY * ySlope + yOffset - // - // where: - // ySlope = (BOTTOMY - TOPY) / (bottomY - topY) - // yOffset = (TOPY - topY * ySlope) - - b16_t topY = (m_calibData[CALIB_UPPER_LEFT_INDEX].y + - m_calibData[CALIB_UPPER_RIGHT_INDEX].y) << 15; - b16_t bottomY = (m_calibData[CALIB_LOWER_LEFT_INDEX].y + - m_calibData[CALIB_LOWER_RIGHT_INDEX].y) << 15; + m_calthread = CALTHREAD_SHOW; + (void)pthread_kill(m_thread, CONFIG_NXWM_CALIBRATION_SIGNO); + } +} - data.ySlope = b16divb16(itob16(CALIBRATION_BOTTOMY - CALIBRATION_TOPY), (bottomY - topY)); - data.yOffset = itob16(CALIBRATION_TOPY) - b16mulb16(topY, data.ySlope); +/** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ - gdbg("New ySlope: %08x yOffset: %08x\n", data.ySlope, data.yOffset); - return true; +bool CCalibration::isFullScreen(void) const +{ + return m_window->isFullScreen(); } /** @@ -347,7 +320,7 @@ void CCalibration::touchscreenInput(struct touch_sample_s &sample) // Yes.. invoke the state machine. gvdbg("State: %d Screen x: %d y: %d Touch x: %d y: %d\n", - m_state, m_screenInfo.pos.x, m_screenInfo.pos.y, + m_calphase, m_screenInfo.pos.x, m_screenInfo.pos.y, m_touchPos.x, m_touchPos.y); stateMachine(); @@ -367,6 +340,139 @@ void CCalibration::touchscreenInput(struct touch_sample_s &sample) } } +/** + * Start the calibration thread. + * + * @param initialState. The initial state of the calibration thread + * @return True if the thread was successfully started. + */ + +bool CCalibration::startCalibration(enum ECalThreadState initialState) +{ + + // Verify that the thread is not already running + + if (isRunning()) + { + gdbg("The calibration thread is already running\n"); + return false; + } + + // Configure the calibration thread + + pthread_attr_t attr; + (void)pthread_attr_init(&attr); + + struct sched_param param; + param.sched_priority = CONFIG_NXWM_CALIBRATION_LISTENERPRIO; + (void)pthread_attr_setschedparam(&attr, ¶m); + + (void)pthread_attr_setstacksize(&attr, CONFIG_NXWM_CALIBRATION_LISTENERSTACK); + + // Set the initial state of the thread + + m_calthread = initialState; + + // Start the thread that will perform the calibration process + + int ret = pthread_create(&m_thread, &attr, calibration, (FAR void *)this); + if (ret != 0) + { + gdbg("pthread_create failed: %d\n", ret); + return false; + } + + // Detach from the pthread so that we do not have any memory leaks + + (void)pthread_detach(m_thread); + + gvdbg("Calibration thread m_calthread=%d\n", (int)m_calthread); + return true; +} + +/** + * The calibration thread. This is the entry point of a thread that provides the + * calibration displays, waits for input, and collects calibration data. + * + * @param arg. The CCalibration 'this' pointer cast to a void*. + * @return This function always returns NULL when the thread exits + */ + +FAR void *CCalibration::calibration(FAR void *arg) +{ + CCalibration *This = (CCalibration *)arg; + bool stalled = true; + + // The calibration thread is now running + + This->m_calthread = CALTHREAD_RUNNING; + This->m_calphase = CALPHASE_NOT_STARTED; + gvdbg("Started: m_calthread=%d\n", (int)This->m_calthread); + + // Loop until calibration completes or we have been requested to terminate + + while (This->m_calthread != CALTHREAD_STOPREQUESTED && + This->m_calphase != CALPHASE_COMPLETE) + { + // Check for state changes due to display order changes + + if (This->m_calthread == CALTHREAD_HIDE) + { + // This state is set by hide() when our display is no longer visible + + This->m_calthread = CALTHREAD_RUNNING; + This->m_calphase = CALPHASE_NOT_STARTED; + stalled = true; + } + else if (This->m_calthread == CALTHREAD_SHOW) + { + // This state is set by redraw() when our display has become visible + + This->m_calthread = CALTHREAD_RUNNING; + This->m_calphase = CALPHASE_NOT_STARTED; + stalled = false; + This->stateMachine(); + } + + // The calibration thread will stall if has been asked to hide the + // display. While stalled, we will just sleep for a bit abd test + // the state again. If we are re-awakened by a redraw(), then we + // will be given a signal which will wake us up immediately. + // + // Note that stalled is also initially true so we have to receive + // redraw() before we attempt to draw anything + + if (stalled) + { + // Sleep for a while (or until we receive a signal) + + std::usleep(500*1000); + } + else + { + // Wait for the next raw touchscreen input (or possibly a signal) + + struct touch_sample_s sample; + while (!This->m_touchscreen->waitRawTouchData(&sample) && + This->m_calthread == CALTHREAD_RUNNING); + + // Then process the raw touchscreen input + + if (This->m_calthread == CALTHREAD_RUNNING) + { + This->touchscreenInput(sample); + } + } + } + + // Perform the final steps of calibration + + This->finishCalibration(); + + gvdbg("Terminated: m_calthread=%d\n", (int)This->m_calthread); + return (FAR void *)0; +} + /** * This is the calibration state machine. It is called initially and then * as new touchscreen data is received. @@ -374,6 +480,8 @@ void CCalibration::touchscreenInput(struct touch_sample_s &sample) void CCalibration::stateMachine(void) { + gvdbg("Old m_calphase=%d\n", m_calphase); + // Recover the window instance contained in the full screen window NXWidgets::INxWindow *window = m_window->getWindow(); @@ -386,10 +494,10 @@ void CCalibration::stateMachine(void) return; } - switch (m_state) + switch (m_calphase) { default: - case CALIB_NOT_STARTED: + case CALPHASE_NOT_STARTED: { // Clear the entire screen // Get the widget control associated with the full screen window @@ -415,13 +523,13 @@ void CCalibration::stateMachine(void) // Then set up the current state - m_state = CALIB_UPPER_LEFT; + m_calphase = CALPHASE_UPPER_LEFT; } break; - case CALIB_UPPER_LEFT: + case CALPHASE_UPPER_LEFT: { - // A touch has been received while in the CALIB_UPPER_LEFT state. + // A touch has been received while in the CALPHASE_UPPER_LEFT state. // Save the touch data and set up the next calibration display m_calibData[CALIB_UPPER_LEFT_INDEX].x = m_touchPos.x; @@ -444,13 +552,13 @@ void CCalibration::stateMachine(void) // Then set up the current state - m_state = CALIB_UPPER_RIGHT; + m_calphase = CALPHASE_UPPER_RIGHT; } break; - case CALIB_UPPER_RIGHT: + case CALPHASE_UPPER_RIGHT: { - // A touch has been received while in the CALIB_UPPER_RIGHT state. + // A touch has been received while in the CALPHASE_UPPER_RIGHT state. // Save the touch data and set up the next calibration display m_calibData[CALIB_UPPER_RIGHT_INDEX].x = m_touchPos.x; @@ -473,13 +581,13 @@ void CCalibration::stateMachine(void) // Then set up the current state - m_state = CALIB_LOWER_RIGHT; + m_calphase = CALPHASE_LOWER_RIGHT; } break; - case CALIB_LOWER_RIGHT: + case CALPHASE_LOWER_RIGHT: { - // A touch has been received while in the CALIB_LOWER_RIGHT state. + // A touch has been received while in the CALPHASE_LOWER_RIGHT state. // Save the touch data and set up the next calibration display m_calibData[CALIB_LOWER_RIGHT_INDEX].x = m_touchPos.x; @@ -502,32 +610,38 @@ void CCalibration::stateMachine(void) // Then set up the current state - m_state = CALIB_LOWER_LEFT; + m_calphase = CALPHASE_LOWER_LEFT; } break; - case CALIB_LOWER_LEFT: + case CALPHASE_LOWER_LEFT: { - // A touch has been received while in the CALIB_LOWER_LEFT state. + // A touch has been received while in the CALPHASE_LOWER_LEFT state. // Save the touch data and set up the next calibration display m_calibData[CALIB_LOWER_LEFT_INDEX].x = m_touchPos.x; m_calibData[CALIB_LOWER_LEFT_INDEX].y = m_touchPos.y; + // Clear the previous screen by re-drawing it using the backgro9und + // color. That is much faster than clearing the whole display + + m_screenInfo.lineColor = CONFIG_NXWM_CALIBRATION_BACKGROUNDCOLOR; + m_screenInfo.circleFillColor = CONFIG_NXWM_CALIBRATION_BACKGROUNDCOLOR; + showCalibration(); + // Inform any waiter that calibration is complete - m_state = CALIB_COMPLETE; - sem_post(&m_waitSem); + m_calphase = CALPHASE_COMPLETE; } break; - case CALIB_COMPLETE: + case CALPHASE_COMPLETE: // Might happen... do nothing if it does break; } - gvdbg("State: %d Screen x: %d y: %d\n", - m_state, m_screenInfo.pos.x, m_screenInfo.pos.y); + gvdbg("New m_calphase=%d Screen x: %d y: %d\n", + m_calphase, m_screenInfo.pos.x, m_screenInfo.pos.y); } /** @@ -573,3 +687,105 @@ void CCalibration::showCalibration(void) port->drawFilledRect(m_screenInfo.pos.x, 0, CALIBRATION_LINE_THICKNESS, windowSize.h, m_screenInfo.lineColor); } + +/** + * Finish calibration steps and provide the calibration data to the + * touchscreen driver. + */ + +void CCalibration::finishCalibration(void) +{ + // Did we finish calibration successfully? + + if (m_calphase == CALPHASE_COMPLETE) + { + // Yes... Get the final Calibration data + + struct SCalibrationData caldata; + if (createCalibrationData(caldata)) + { + // And provide this to the touchscreen, enabling touchscreen processing + + m_touchscreen->setEnabled(false); + m_touchscreen->setCalibrationData(caldata); + m_touchscreen->setEnabled(true); + } + } + + // Remove the touchscreen application from the taskbar + + m_taskbar->stopApplication(this); + + // And set the terminated stated + + m_calthread = CALTHREAD_TERMINATED; +} + +/** + * Given the raw touch data collected by the calibration thread, create the + * massaged calibration data needed by CTouchscreen. + * + * @param data. A reference to the location to save the calibration data + * @return True if the calibration data was successfully created. + */ + +bool CCalibration::createCalibrationData(struct SCalibrationData &data) +{ + // Recover the window instance contained in the full screen window + + NXWidgets::INxWindow *window = m_window->getWindow(); + + // Get the size of the fullscreen window + + struct nxgl_size_s windowSize; + if (!window->getSize(&windowSize)) + { + gdbg("NXWidgets::INxWindow::getSize failed\n"); + return false; + } + + // Calculate the calibration parameters + // + // (scaledX - LEFTX) / (rawX - leftX) = (RIGHTX - LEFTX) / (rightX - leftX) + // scaledX = (rawX - leftX) * (RIGHTX - LEFTX) / (rightX - leftX) + LEFTX + // = rawX * xSlope + (LEFTX - leftX * xSlope) + // = rawX * xSlope + xOffset + // + // where: + // xSlope = (RIGHTX - LEFTX) / (rightX - leftX) + // xOffset = (LEFTX - leftX * xSlope) + + b16_t leftX = (m_calibData[CALIB_UPPER_LEFT_INDEX].x + + m_calibData[CALIB_LOWER_LEFT_INDEX].x) << 15; + b16_t rightX = (m_calibData[CALIB_UPPER_RIGHT_INDEX].x + + m_calibData[CALIB_LOWER_RIGHT_INDEX].x) << 15; + + data.xSlope = b16divb16(itob16(CALIBRATION_RIGHTX - CALIBRATION_LEFTX), (rightX - leftX)); + data.xOffset = itob16(CALIBRATION_LEFTX) - b16mulb16(leftX, data.xSlope); + + gdbg("New xSlope: %08x xOffset: %08x\n", data.xSlope, data.xOffset); + + // Similarly for Y + // + // (scaledY - TOPY) / (rawY - topY) = (BOTTOMY - TOPY) / (bottomY - topY) + // scaledY = (rawY - topY) * (BOTTOMY - TOPY) / (bottomY - topY) + TOPY + // = rawY * ySlope + (TOPY - topY * ySlope) + // = rawY * ySlope + yOffset + // + // where: + // ySlope = (BOTTOMY - TOPY) / (bottomY - topY) + // yOffset = (TOPY - topY * ySlope) + + b16_t topY = (m_calibData[CALIB_UPPER_LEFT_INDEX].y + + m_calibData[CALIB_UPPER_RIGHT_INDEX].y) << 15; + b16_t bottomY = (m_calibData[CALIB_LOWER_LEFT_INDEX].y + + m_calibData[CALIB_LOWER_RIGHT_INDEX].y) << 15; + + data.ySlope = b16divb16(itob16(CALIBRATION_BOTTOMY - CALIBRATION_TOPY), (bottomY - topY)); + data.yOffset = itob16(CALIBRATION_TOPY) - b16mulb16(topY, data.ySlope); + + gdbg("New ySlope: %08x yOffset: %08x\n", data.ySlope, data.yOffset); + return true; +} + + diff --git a/NxWidgets/nxwm/src/cfullscreenwindow.cxx b/NxWidgets/nxwm/src/cfullscreenwindow.cxx index 2087543cd..7d63b02d7 100644 --- a/NxWidgets/nxwm/src/cfullscreenwindow.cxx +++ b/NxWidgets/nxwm/src/cfullscreenwindow.cxx @@ -137,6 +137,19 @@ void CFullScreenWindow::setWindowLabel(NXWidgets::CNxString &appname) { } +/** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + +bool CFullScreenWindow::isFullScreen(void) const +{ + return true; +} + /** * Register to receive callbacks when toolbar icons are selected */ diff --git a/NxWidgets/nxwm/src/cnxconsole.cxx b/NxWidgets/nxwm/src/cnxconsole.cxx index 5ee12d36f..264845a03 100644 --- a/NxWidgets/nxwm/src/cnxconsole.cxx +++ b/NxWidgets/nxwm/src/cnxconsole.cxx @@ -326,6 +326,19 @@ void CNxConsole::redraw(void) nxcon_redraw(m_nxcon, &rect, false); } +/** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + +bool CNxConsole::isFullScreen(void) const +{ + return m_window->isFullScreen(); +} + /** * This is the NxConsole task. This function first redirects output to the * console window. diff --git a/NxWidgets/nxwm/src/cstartwindow.cxx b/NxWidgets/nxwm/src/cstartwindow.cxx index f907f6718..ceeff0d7b 100644 --- a/NxWidgets/nxwm/src/cstartwindow.cxx +++ b/NxWidgets/nxwm/src/cstartwindow.cxx @@ -279,6 +279,19 @@ void CStartWindow::redraw(void) } } +/** + * Report of this is a "normal" window or a full screen window. The + * primary purpose of this method is so that window manager will know + * whether or not it show draw the task bar. + * + * @return True if this is a full screen window. + */ + +bool CStartWindow::isFullScreen(void) const +{ + return m_window->isFullScreen(); +} + /** * Add the application to the start window. The general sequence for * setting up the start window is: diff --git a/NxWidgets/nxwm/src/ctaskbar.cxx b/NxWidgets/nxwm/src/ctaskbar.cxx index f5a5c08f5..3305b945b 100644 --- a/NxWidgets/nxwm/src/ctaskbar.cxx +++ b/NxWidgets/nxwm/src/ctaskbar.cxx @@ -39,6 +39,8 @@ #include +#include + #include #include "crect.hxx" @@ -235,16 +237,75 @@ bool CTaskbar::startWindowManager(void) m_started = true; - // Draw the taskbar + // Decide which application will be the initial 'top' application + + m_topApp = (IApplication *)0; + int topIndex = -1; + + // No.. Search for that last, non-minimized application (there might not be one) - if (!redrawTaskbarWindow()) + for (int i = m_slots.size() - 1; i >= 0; i--) { - return false; + IApplication *candidate = m_slots.at(i).app; + if (!candidate->isMinimized()) + { + m_topApp = candidate; + topIndex = i; + break; + } } + gvdbg("m_topApp=%p topIndex=%d\n", m_topApp, topIndex); - // Draw the top application window + // Now start each application (whatever that means to the application) - return redrawTopWindow(); + for (int i = 0; i < m_slots.size(); ) + { + IApplication *app = m_slots.at(i).app; + + gvdbg("Starting app[%d]\n", i); + if (!app->run()) + { + // Call stopApplication on a failure to start. This will call + // app->stop() (which is probably not necesary for the application + // but it should be prepared/ to handle it). stopApplication() + // will also removed the icon image from the list and delete it. + + stopApplication(app); + + // Then continue with the next application. Notice that i is + // not incremented in this case and we will continue with the + // next application which will not be at this same index + + continue; + } + + // Hide all appliations except for the top application + + if (i != topIndex) + { + // Bring the application up in the non-visible state (the + // application may or may not be minimized, but it is not + // visible now). + + gvdbg("Hiding app[%d]\n", i); + hideApplicationWindow(app); + } + else + { + // Bring up the application as the new top application + + gvdbg("Showing app[%d]\n", i); + topApplication(app); + } + + // The application was successfully initialized.. index to the next application + + i++; + } + + // Draw the taskbar. It will be draw at a higher level than the application. + + return redrawTaskbarWindow(); } return false; @@ -391,41 +452,48 @@ bool CTaskbar::startApplication(IApplication *app, bool minimized) slot.image = image; m_slots.push_back(slot); - // Start the application (whatever that means). + // Initialize the application states + + app->setTopApplication(false); + app->setMinimized(minimized); - if (!app->run()) + // Has the window manager been started? + + if (m_started) { - // Call stopApplication on a failure to start. This will call - // app->stop() (which is probably not necesary for the application - // but it should be prepared/ to handle it). stopApplication() - // will also removed the icon image from the list and delete it. + // Yes.. Start the application (whatever that means). - stopApplication(app); - return false; - } + if (!app->run()) + { + // Call stopApplication on a failure to start. This will call + // app->stop() (which is probably not necesary for the application + // but it should be prepared/ to handle it). stopApplication() + // will also removed the icon image from the list and delete it. - // Has the window manager been started? Or were we ask to start - // the application minimized? + stopApplication(app); + return false; + } - if (minimized || !m_started) - { - // Bring the application up in the minimized state + // Has the window manager been started? Or were we ask to start + // the application minimized? - hideApplicationWindow(app); - } - else - { - // Bring up the application as the new top application + if (minimized) + { + // Bring the minimized application up in non-visible state - app->setTopApplication(false); - app->setMinimized(false); - topApplication(app); - } + hideApplicationWindow(app); + } + else + { + // Bring up the application as the new top application if we are running + // If not, we will select and bring up the top application when the + // window manager is started - // Redraw the task bar with the new icon (if we have been started) + topApplication(app); + } + + // Redraw the task bar with the new icon (if we have been started) - if (m_started) - { redrawTaskbarWindow(); } @@ -451,7 +519,11 @@ bool CTaskbar::topApplication(IApplication *app) if (m_topApp) { - // Yes.. then disable it + // Yes.. then minimize the application + + app->setMinimized(true); + + // And make the application non-visible hideApplicationWindow(m_topApp); } @@ -501,6 +573,7 @@ bool CTaskbar::minimizeApplication(IApplication *app) // No, then we are going to minimize it but disabling its components, // marking it as minimized, then raising a new window to the top window. + app->setMinimized(true); hideApplicationWindow(app); // Re-draw the new top, non-minimized application @@ -521,13 +594,22 @@ bool CTaskbar::minimizeApplication(IApplication *app) bool CTaskbar::stopApplication(IApplication *app) { - // First, minimize the application. That will move the application - // to the bottom of the hiearachy and redraw the next application - // (If the application is already minimized, it does nothing) + // Make the application minimized and make sure that it is not the top + // application. - minimizeApplication(app); + app->setMinimized(true); + if (app->isTopApplication()) + { + app->setTopApplication(false); + m_topApp = (IApplication *)0; + } + + // Hide the application window. That will move the application to the + // bottom of the hiearachy. + + hideApplicationWindow(app); - // Stop the application + // Stop the application (whatever this means to the application) app->stop(); @@ -540,7 +622,7 @@ bool CTaskbar::stopApplication(IApplication *app) IApplication *candidate = m_slots.at(i).app; if (candidate == app) { - // Yes.. found it. Delete the icon image and remove it + // Yes.. found it. Delete the icon image and remove the entry // from the list of applications delete m_slots.at(i).image; @@ -549,9 +631,16 @@ bool CTaskbar::stopApplication(IApplication *app) } } - // And redraw the task bar (without the icon for this task) + // Re-draw the new top, non-minimized application - return redrawTaskbarWindow(); + bool ret = redrawTopWindow(); + if (ret) + { + // And redraw the task bar (without the icon for this task) + + ret = redrawTaskbarWindow(); + } + return ret; } /** @@ -895,116 +984,126 @@ bool CTaskbar::createBackgroundImage(void) bool CTaskbar::redrawTaskbarWindow(void) { - // Get the widget control from the task bar + // Only redraw the task bar if (1) the window manager has been started, AND + // (2) there is no top window (i.e., we are showing the background image), OR + // (3) there is a top window, but it is not full screen - NXWidgets::CWidgetControl *control = m_taskbar->getWidgetControl(); + if (m_started && (!m_topApp || !m_topApp->isFullScreen())) + { + // Get the widget control from the task bar - // Get the graphics port for drawing on the background window + NXWidgets::CWidgetControl *control = m_taskbar->getWidgetControl(); - NXWidgets::CGraphicsPort *port = control->getGraphicsPort(); + // Get the graphics port for drawing on the background window - // Get the size of the window + NXWidgets::CGraphicsPort *port = control->getGraphicsPort(); - struct nxgl_size_s windowSize; - if (!m_taskbar->getSize(&windowSize)) - { - return false; - } + // Get the size of the window - // Raise the task bar to the top of the display. This is only necessary - // after stopping a full screen application. Other applications do not - // overlap the task bar and, hence, do not interfere. + struct nxgl_size_s windowSize; + if (!m_taskbar->getSize(&windowSize)) + { + return false; + } - m_taskbar->raise(); + // Raise the task bar to the top of the display. This is only necessary + // after stopping a full screen application. Other applications do not + // overlap the task bar and, hence, do not interfere. - // Fill the entire window with the background color + m_taskbar->raise(); - port->drawFilledRect(0, 0, windowSize.w, windowSize.h, - CONFIG_NXWM_DEFAULT_BACKGROUNDCOLOR); + // Fill the entire window with the background color - // Add a border to the task bar to delineate it from the background window + port->drawFilledRect(0, 0, windowSize.w, windowSize.h, + CONFIG_NXWM_DEFAULT_BACKGROUNDCOLOR); - port->drawBevelledRect(0, 0, windowSize.w, windowSize.h, - CONFIG_NXWM_DEFAULT_SHINEEDGECOLOR, - CONFIG_NXWM_DEFAULT_SHADOWEDGECOLOR); + // Add a border to the task bar to delineate it from the background window + + port->drawBevelledRect(0, 0, windowSize.w, windowSize.h, + CONFIG_NXWM_DEFAULT_SHINEEDGECOLOR, + CONFIG_NXWM_DEFAULT_SHADOWEDGECOLOR); - // Begin adding icons in the upper left corner + // Begin adding icons in the upper left corner - struct nxgl_point_s taskbarPos; + struct nxgl_point_s taskbarPos; #if defined(CONFIG_NXWM_TASKBAR_TOP) || defined(CONFIG_NXWM_TASKBAR_BOTTOM) - taskbarPos.x = CONFIG_NXWM_TASKBAR_HSPACING; - taskbarPos.y = 0; + taskbarPos.x = CONFIG_NXWM_TASKBAR_HSPACING; + taskbarPos.y = 0; #else - taskbarPos.x = 0; - taskbarPos.y = CONFIG_NXWM_TASKBAR_VSPACING; + taskbarPos.x = 0; + taskbarPos.y = CONFIG_NXWM_TASKBAR_VSPACING; #endif - // Add each icon in the list of applications + // Add each icon in the list of applications - for (int i = 0; i < m_slots.size(); i++) - { - // Get the icon associated with this application + for (int i = 0; i < m_slots.size(); i++) + { + // Get the icon associated with this application - NXWidgets::CImage *image = m_slots.at(i).image; + NXWidgets::CImage *image = m_slots.at(i).image; - // Disable drawing of the icon image; disable events from the icon + // Disable drawing of the icon image; disable events from the icon - image->disableDrawing(); - image->setRaisesEvents(false); + image->disableDrawing(); + image->setRaisesEvents(false); - // Get the size of the icon image + // Get the size of the icon image - NXWidgets::CRect rect; - image->getPreferredDimensions(rect); + NXWidgets::CRect rect; + image->getPreferredDimensions(rect); - // Position the icon + // Position the icon - struct nxgl_point_s iconPos; + struct nxgl_point_s iconPos; #if defined(CONFIG_NXWM_TASKBAR_TOP) || defined(CONFIG_NXWM_TASKBAR_BOTTOM) - // For horizontal task bars, the icons will be aligned along the top of - // the task bar + // For horizontal task bars, the icons will be aligned along the top of + // the task bar - iconPos.x = taskbarPos.x; - iconPos.y = taskbarPos.y + CONFIG_NXWM_TASKBAR_VSPACING; + iconPos.x = taskbarPos.x; + iconPos.y = taskbarPos.y + CONFIG_NXWM_TASKBAR_VSPACING; #else - // For vertical task bars, the icons will be centered horizontally + // For vertical task bars, the icons will be centered horizontally - iconPos.x = (windowSize.w - rect.getWidth()) >> 1; - iconPos.y = taskbarPos.y; + iconPos.x = (windowSize.w - rect.getWidth()) >> 1; + iconPos.y = taskbarPos.y; #endif - // Set the position of the icon bitmap + // Set the position of the icon bitmap - (void)image->moveTo(iconPos.x, iconPos.y); + (void)image->moveTo(iconPos.x, iconPos.y); - // Then re-draw the icon at the new position + // Then re-draw the icon at the new position - image->enableDrawing(); - image->redraw(); - image->setRaisesEvents(true); + image->enableDrawing(); + image->redraw(); + image->setRaisesEvents(true); - // Do we add icons left-to-right? Or top-to-bottom? + // Do we add icons left-to-right? Or top-to-bottom? #if defined(CONFIG_NXWM_TASKBAR_TOP) || defined(CONFIG_NXWM_TASKBAR_BOTTOM) - // left-to-right ... increment the X display position + // left-to-right ... increment the X display position - taskbarPos.x += rect.getWidth() + CONFIG_NXWM_TASKBAR_HSPACING; - if (taskbarPos.x > windowSize.w) - { - break; - } + taskbarPos.x += rect.getWidth() + CONFIG_NXWM_TASKBAR_HSPACING; + if (taskbarPos.x > windowSize.w) + { + break; + } #else - // top-to-bottom ... increment the Y display position + // top-to-bottom ... increment the Y display position - taskbarPos.y += rect.getHeight() + CONFIG_NXWM_TASKBAR_VSPACING; - if (taskbarPos.y > windowSize.h) - { - break; - } + taskbarPos.y += rect.getHeight() + CONFIG_NXWM_TASKBAR_VSPACING; + if (taskbarPos.y > windowSize.h) + { + break; + } #endif + } } + // Return success (it is not a failure if the window manager is not started + // or the task bar is occluded by a full screen window. + return true; } @@ -1158,10 +1257,6 @@ void CTaskbar::hideApplicationWindow(IApplication *app) app->setTopApplication(false); } - // Make sure that the application is marked as minimized. - - app->setMinimized(true); - // We do not need to lower the application to the back.. the new top // window will be raised instead. // diff --git a/NxWidgets/nxwm/src/ctouchscreen.cxx b/NxWidgets/nxwm/src/ctouchscreen.cxx index 21ccc91e3..1a8a5e967 100644 --- a/NxWidgets/nxwm/src/ctouchscreen.cxx +++ b/NxWidgets/nxwm/src/ctouchscreen.cxx @@ -159,17 +159,17 @@ bool CTouchscreen::start(void) (void)pthread_attr_init(&attr); struct sched_param param; - param.sched_priority = CONFIG_NXWIDGETS_LISTENERPRIO; + param.sched_priority = CONFIG_NXWM_TOUCHSCREEN_LISTENERPRIO; (void)pthread_attr_setschedparam(&attr, ¶m); - (void)pthread_attr_setstacksize(&attr, CONFIG_NXWIDGETS_LISTENERSTACK); + (void)pthread_attr_setstacksize(&attr, CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK); m_state = LISTENER_STARTED; // The listener thread has been started, but is not yet running int ret = pthread_create(&m_thread, &attr, listener, (FAR void *)this); if (ret != 0) { - dbg("NxServer::connect: pthread_create failed: %d\n", ret); + dbg("CTouchscreen::start: pthread_create failed: %d\n", ret); return false; } @@ -204,7 +204,7 @@ bool CTouchscreen::start(void) * @param data. A reference to the touchscreen data. */ -void CTouchscreen::setCalibrationData(struct SCalibrationData &caldata) +void CTouchscreen::setCalibrationData(const struct SCalibrationData &caldata) { // Save a copy of the calibration data -- cgit v1.2.3