From d97899b6e2c22b4f33f23a8333a03cd323bcd45e Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 9 May 2012 19:31:48 +0000 Subject: NxWidgets: Remove modal loops, Add CWindowEventHandler*. NxWM: Add support for full screen applications git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4716 42af7a65-404d-4744-a932-0658087f49c3 --- NxWidgets/libnxwidgets/Makefile | 2 +- NxWidgets/libnxwidgets/include/cnxwidget.hxx | 24 --- NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx | 122 ++++++++++---- .../libnxwidgets/include/cwindoweventhandler.hxx | 113 +++++++++++++ .../include/cwindoweventhandlerlist.hxx | 168 ++++++++++++++++++ NxWidgets/libnxwidgets/include/nxconfig.hxx | 4 + NxWidgets/libnxwidgets/src/cnxserver.cxx | 20 +-- NxWidgets/libnxwidgets/src/cnxwidget.cxx | 53 ------ NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx | 187 +++++++++++---------- 9 files changed, 484 insertions(+), 209 deletions(-) create mode 100644 NxWidgets/libnxwidgets/include/cwindoweventhandler.hxx create mode 100644 NxWidgets/libnxwidgets/include/cwindoweventhandlerlist.hxx (limited to 'NxWidgets/libnxwidgets') diff --git a/NxWidgets/libnxwidgets/Makefile b/NxWidgets/libnxwidgets/Makefile index b35039e01..2520e419d 100644 --- a/NxWidgets/libnxwidgets/Makefile +++ b/NxWidgets/libnxwidgets/Makefile @@ -46,7 +46,7 @@ CXXSRCS += clistdata.cxx clistdataitem.cxx cnxfont.cxx CXXSRCS += cnxserver.cxx cnxstring.cxx cnxtimer.cxx cnxwidget.cxx cnxwindow.cxx CXXSRCS += cnxtkwindow.cxx cnxtoolbar.cxx crect.cxx crlepalettebitmap.cxx CXXSRCS += cstringiterator.cxx ctext.cxx cwidgetcontrol.cxx cwidgeteventhandlerlist.cxx -CXXSRCS += singletons.cxx +CXXSRCS += cwindoweventhandlerlist.cxx singletons.cxx # Widget APIs CXXSRCS += cbutton.cxx cbuttonarray.cxx ccheckbox.cxx ccyclebutton.cxx CXXSRCS += cglyphbutton.cxx cimage.cxx ckeypad.cxx clabel.cxx clatchbutton.cxx diff --git a/NxWidgets/libnxwidgets/include/cnxwidget.hxx b/NxWidgets/libnxwidgets/include/cnxwidget.hxx index d29830c0a..4c470cfb2 100644 --- a/NxWidgets/libnxwidgets/include/cnxwidget.hxx +++ b/NxWidgets/libnxwidgets/include/cnxwidget.hxx @@ -154,7 +154,6 @@ namespace NXWidgets uint8_t visibleRegionCacheInvalid : 1; /**< True if the region cache is invalid. */ uint8_t hidden : 1; /**< True if the widget is hidden. */ uint8_t doubleClickable : 1; /**< True if the widget can be double-clicked. */ - uint8_t modal : 1; /**< True if the widget is modal. */ } Flags; /** @@ -564,14 +563,6 @@ namespace NXWidgets return m_flags.dragging; } - /** - * Is the widget modal? Only true if the Widget singleton is also modal. - * - * @return True if the widget is modal. - */ - - const bool isModal(void) const; - /** * Get the width of the widget. * @@ -1297,21 +1288,6 @@ namespace NXWidgets bool removeChild(CNxWidget *widget); - /** - * Run the widget modally. - */ - - void goModal(void); - - /** - * Stop the widget running modally. - */ - - inline void stopModal(void) - { - m_flags.modal = false; - } - /** * Get the child widget at the specified index. * diff --git a/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx b/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx index aedec610e..4a54469d8 100644 --- a/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx +++ b/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx @@ -52,6 +52,8 @@ #include "cnxwidget.hxx" #include "crect.hxx" #include "cwidgetstyle.hxx" +#include "cwindoweventhandler.hxx" +#include "cwindoweventhandlerlist.hxx" #include "tnxarray.hxx" /**************************************************************************** @@ -165,11 +167,15 @@ namespace NXWidgets awaiting deletion. */ TNxArray m_widgets; /**< List of controlled widgets. */ - bool m_modal; /**< True: in modal loop */ bool m_haveGeometry; /**< True: indicates that we have valid geometry data. */ - sem_t m_modalSem; /**< Modal loops waits for +#ifdef CONFIG_NXWIDGET_EVENTWAIT + bool m_waiting; /**< True: Extternal logic waiting for + window event */ + sem_t m_waitSem; /**< External loops waits for events on this semaphore */ +#endif + /** * I/O */ @@ -198,6 +204,7 @@ namespace NXWidgets #ifdef CONFIG_NX_MULTIUSER sem_t m_geoSem; /**< Posted when geometry is valid */ #endif + CWindowEventHandlerList m_eventHandlers; /**< List of event handlers. */ /** * Style @@ -227,15 +234,15 @@ namespace NXWidgets /** * Pass clicks to the widget hierarchy. Closes the context menu if * the clicked widget is not the context menu. If a single widget - * is supplied, only that widget is sent the click. That widget - * should be running modally. + * is supplied, only that widget is sent the click. * * @param x Click xcoordinate. * @param y Click ycoordinate. - * @param widget Pointer to a modally-running widget or NULL. + * @param widget. Specific widget to poll. Use NULL to run the + * all widgets in the window. */ - void handleLeftClick(nxgl_coord_t x, nxgl_coord_t y, CNxWidget* widget); + void handleLeftClick(nxgl_coord_t x, nxgl_coord_t y, CNxWidget *widget); /** * Get the index of the specified controlled widget. @@ -255,8 +262,8 @@ namespace NXWidgets /** * Process mouse/touchscreen events and send throughout the hierarchy. * - * @param widget to process, used for modal widgets; omit this parameter - * to run the whole system. + * @param widget. Specific widget to poll. Use NULL to run the + * all widgets in the window. * @return True means a mouse event occurred */ @@ -279,10 +286,12 @@ namespace NXWidgets bool pollCursorControlEvents(void); /** - * Wake up the modal loop + * Wake up and external logic that is waiting for a window event. */ - void wakeupModalLoop(void); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + void postWindowEvent(void); +#endif /** * Take the geometry semaphore (handling signal interruptions) @@ -340,42 +349,62 @@ namespace NXWidgets ~CWidgetControl(void); /** - * Run the widget modally. This will run the CWidgetControl - * application until stopModal() is called. - */ - - void goModal(void); - - /** - * Wait for an interesting modal event to occur (like a mouse or keyboard event) + * Wait for an interesting window event to occur (like a mouse or keyboard event) + * Caller's should exercise care to assure that the test for waiting and this + * call are "atomic" .. perhaps by locking the scheduler like: + * + * sched_lock(); + * + * if () + * { + * window->waitForWindowEvent(); + * } + * sched_unlock(); */ - void waitForModalEvent(void); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + void waitForWindowEvent(void); +#endif /** - * Is the widget modal? Only true if the Widget singleton is also modal. + * Is external logic awaiting for a window event? * - * @return True if the widget is modal. + * @return True if the widget if external logic is waiting. */ - inline const bool isModal(void) const +#ifdef CONFIG_NXWIDGET_EVENTWAIT + inline const bool isWaiting(void) const { - return m_modal; + return m_waiting; } - - /** - * Stop the widget running modally. - */ - - void stopModal(void); +#endif /** * Run all code that needs to take place on a periodic basis. - * This is normally called from and is the main body of goModal() - * with widget == NULL. + * This method normally called externally... either periodically + * or when a window event is detected. If CONFIG_NXWIDGET_EVENTWAIT + * is defined, then external logic want call waitWindow event and + * when awakened, they chould call this function. As an example: + * + * for (;;) + * { + * sched_lock(); // Make the sequence atomic + * if (!window->pollEvents(0)) + * { + * window->waitWindowEvent(); + * } + * sched_unlock(); + * } + * + * This method is just a wrapper simply calls the followi. + * + * processDeleteQueue() + * pollMouseEvents(widget) + * pollKeyboardEvents() + * pollCursorControlEvents() * - * @param widget Sub-widget to run, used for modal widgets; omit - * this parameter to run the whole system. + * @param widget. Specific widget to poll. Use NULL to run the + * all widgets in the window. * @return True means some interesting event occurred */ @@ -551,8 +580,10 @@ namespace NXWidgets * @param nCh The number of characters that are available in pStr[]. * @param pStr The array of characters. */ - + +#ifdef CONFIG_NX_KBD void newKeyboardEvent(uint8_t nCh, FAR const uint8_t *pStr); +#endif /** * This event means that cursor control data is available for the window. @@ -673,6 +704,29 @@ namespace NXWidgets { return m_port; } + + /** + * Adds a window event handler. The window handler will receive + * notification all NX events received by this window\. + * + * @param eventHandler A pointer to the event handler. + */ + + inline void addWindowEventHandler(CWindowEventHandler *eventHandler) + { + m_eventHandlers.addWindowEventHandler(eventHandler); + } + + /** + * Remove a window event handler. + * + * @param eventHandler A pointer to the event handler to remove. + */ + + inline void removeWindowEventHandler(CWindowEventHandler *eventHandler) + { + m_eventHandlers.removeWindowEventHandler(eventHandler); + } }; } diff --git a/NxWidgets/libnxwidgets/include/cwindoweventhandler.hxx b/NxWidgets/libnxwidgets/include/cwindoweventhandler.hxx new file mode 100644 index 000000000..1cea0ba68 --- /dev/null +++ b/NxWidgets/libnxwidgets/include/cwindoweventhandler.hxx @@ -0,0 +1,113 @@ +/**************************************************************************** + * NxWidgets/libnxwidgets/include/cwindoweventhandler.hxx + * + * Copyright (C) 2012 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, NxWidgets, nor the names of its contributors + * me 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 __INCLUDE_CWINDOWEVENTHANDLER_HXX +#define __INCLUDE_CWINDOWEVENTHANDLER_HXX + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nxconfig.hxx" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Implementation Classes + ****************************************************************************/ + +#if defined(__cplusplus) + +namespace NXWidgets +{ + class CNxWidget; + + /** + * Base CWindowEventHandler class, intended to be subclassed. Any class that + * needs to listen for window events should inherit from this class. + */ + + class CWindowEventHandler + { + public: + /** + * Constructor. + */ + + inline CWindowEventHandler() { } + + /** + * Destructor. + */ + + virtual inline ~CWindowEventHandler() { } + + /** + * Handle a NX window redraw request event + */ + + virtual void handleRedrawEvent(void) { } + + /** + * Handle a NX window position/size change event + */ + + virtual void handleGeometryEvent(void) { } + + /** + * Handle an NX window mouse input event. + * + * @param e The event data. + */ + +#ifdef CONFIG_NX_MOUSE + virtual void handleMouseEvent(void) { } +#endif + + /** + * Handle a NX window keyboard input event. + */ + +#ifdef CONFIG_NX_KBD + virtual void handleKeyboardEvent(void) { } +#endif + }; +} + +#endif // __cplusplus + +#endif // __INCLUDE_CWINDOWEVENTHANDLER_HXX diff --git a/NxWidgets/libnxwidgets/include/cwindoweventhandlerlist.hxx b/NxWidgets/libnxwidgets/include/cwindoweventhandlerlist.hxx new file mode 100644 index 000000000..582805691 --- /dev/null +++ b/NxWidgets/libnxwidgets/include/cwindoweventhandlerlist.hxx @@ -0,0 +1,168 @@ +/**************************************************************************** + * NxWidgets/libnxwidgets/include/cwindoweventhandlerlist.hxx + * + * Copyright (C) 2012 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, NxWidgets, nor the names of its contributors + * me 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 __INCLUDE_CWINDOWEVENTHANDLERLIST_HXX +#define __INCLUDE_CWINDOWEVENTHANDLERLIST_HXX + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "cwindoweventhandler.hxx" +#include "tnxarray.hxx" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Implementation Classes + ****************************************************************************/ + +#if defined(__cplusplus) + +namespace NXWidgets +{ + class CListDataItem; + + /** + * List of window event handlers. + */ + class CWindowEventHandlerList + { + protected: + TNxArray m_eventHandlers; /**< List of event handlers */ + + /** + * Return the index to the window event handler. + */ + + bool findWindowEventHandler(CWindowEventHandler *eventHandler, int &index); + + public: + + /** + * Constructor. + * + * @param widget The owning widget. + */ + + CWindowEventHandlerList(void) { } + + /** + * Destructor. + */ + + inline ~CWindowEventHandlerList(void) { } + + /** + * Get the event handler at the specified index. + * + * @param index The index of the event handler. + * @return The event handler at the specified index. + */ + + inline CWindowEventHandler *at(const int index) const + { + return m_eventHandlers.at(index); + } + + /** + * Get the size of the array. + * + * @return The size of the array. + */ + + inline const nxgl_coord_t size(void) const + { + return m_eventHandlers.size(); + } + + /** + * Adds a window event handler. The event handler will receive + * all events raised by this object. + * @param eventHandler A pointer to the event handler. + */ + + void addWindowEventHandler(CWindowEventHandler *eventHandler); + + /** + * Remove a window event handler. + * + * @param eventHandler A pointer to the event handler to remove. + */ + + void removeWindowEventHandler(CWindowEventHandler *eventHandler); + + /** + * Raise the NX window redraw event. + */ + + void raiseRedrawEvent(void); + + /** + * Raise an NX window position/size change event. + */ + + void raiseGeometryEvent(void); + + /** + * Raise an NX mouse window input event. + */ + +#ifdef CONFIG_NX_MOUSE + void raiseMouseEvent(void); +#endif + + /** + * Raise an NX keybord input event + */ + +#ifdef CONFIG_NX_KBD + void raiseKeyboardEvent(void); +#endif + }; +} + +#endif // __cplusplus + +#endif // __INCLUDE_CWINDOWEVENTHANDLERLIST_HXX diff --git a/NxWidgets/libnxwidgets/include/nxconfig.hxx b/NxWidgets/libnxwidgets/include/nxconfig.hxx index 5d3752fd0..5ab883ab1 100644 --- a/NxWidgets/libnxwidgets/include/nxconfig.hxx +++ b/NxWidgets/libnxwidgets/include/nxconfig.hxx @@ -85,6 +85,10 @@ * mode). Default 2048 * CONFIG_NXWIDGETS_LISTENERSTACK - NX listener thread stack size (in multi-user * mode). Default 2048 + * CONFIG_NXWIDGET_EVENTWAIT - Build in support for external window event, modal + * loop management logic. This includes methods to wait for windows events + * to occur so that looping logic can sleep until something interesting + * happens with the window. * * NXWidget Configuration * diff --git a/NxWidgets/libnxwidgets/src/cnxserver.cxx b/NxWidgets/libnxwidgets/src/cnxserver.cxx index 69b1c5c4e..dc6316835 100644 --- a/NxWidgets/libnxwidgets/src/cnxserver.cxx +++ b/NxWidgets/libnxwidgets/src/cnxserver.cxx @@ -215,7 +215,7 @@ bool CNxServer::connect(void) // Start the server task gvdbg("NxServer::connect: Starting server task\n"); - serverId = task_create("NX Server", CONFIG_NXWIDGETS_SERVERPRIO, + serverId = TASK_CREATE("NX Server", CONFIG_NXWIDGETS_SERVERPRIO, CONFIG_NXWIDGETS_SERVERSTACK, server, (FAR const char **)0); if (serverId < 0) { @@ -291,7 +291,7 @@ bool CNxServer::connect(void) #ifndef CONFIG_NX_MULTIUSER void CNxServer::disconnect(void) { - /* Close the server */ + // Close the server if (m_hNxServer) { @@ -324,7 +324,7 @@ void CNxServer::disconnect(void) } } - /* Disconnect from the server */ + // Disconnect from the server if (m_hNxServer) { @@ -346,7 +346,7 @@ int CNxServer::server(int argc, char *argv[]) int ret; #if defined(CONFIG_NXWIDGETS_EXTERNINIT) - /* Use external graphics driver initialization */ + // Use external graphics driver initialization dev = up_nxdrvinit(CONFIG_NXWIDGETS_DEVNO); if (!dev) @@ -356,7 +356,7 @@ int CNxServer::server(int argc, char *argv[]) } #elif defined(CONFIG_NX_LCDDRIVER) - /* Initialize the LCD device */ + // Initialize the LCD device ret = up_lcdinitialize(); if (ret < 0) @@ -365,7 +365,7 @@ int CNxServer::server(int argc, char *argv[]) return EXIT_FAILURE; } - /* Get the device instance */ + // Get the device instance dev = up_lcdgetdev(CONFIG_NXWIDGETS_DEVNO); if (!dev) @@ -374,11 +374,11 @@ int CNxServer::server(int argc, char *argv[]) return EXIT_FAILURE; } - /* Turn the LCD on at 75% power */ + // Turn the LCD on at 75% power (void)dev->setpower(dev, ((3*CONFIG_LCD_MAXPOWER + 3)/4)); #else - /* Initialize the frame buffer device */ + // Initialize the frame buffer device ret = up_fbinitialize(); if (ret < 0) @@ -395,7 +395,7 @@ int CNxServer::server(int argc, char *argv[]) } #endif - /* Then start the server */ + // Then start the server ret = nx_run(dev); gvdbg("nx_run returned: %d\n", errno); @@ -436,7 +436,7 @@ FAR void *CNxServer::listener(FAR void *arg) break; } - /* If we received a message, we must be connected */ + // If we received a message, we must be connected if (!This->m_connected) { diff --git a/NxWidgets/libnxwidgets/src/cnxwidget.cxx b/NxWidgets/libnxwidgets/src/cnxwidget.cxx index 4d8a97627..97d24b73c 100644 --- a/NxWidgets/libnxwidgets/src/cnxwidget.cxx +++ b/NxWidgets/libnxwidgets/src/cnxwidget.cxx @@ -174,7 +174,6 @@ CNxWidget::CNxWidget(CWidgetControl *pWidgetControl, m_flags.erased = true; m_flags.visibleRegionCacheInvalid = true; m_flags.hidden = false; - m_flags.modal = false; // Set hierarchy pointers @@ -397,17 +396,6 @@ const bool CNxWidget::isEnabled() const return false; } -/** - * Is the widget modal? Only true if the Widget singleton is also modal. - * - * @return True if the widget is modal. - */ - -const bool CNxWidget::isModal(void) const -{ - return m_widgetControl->isModal() & m_flags.modal; -} - /** * Insert the dimensions that this widget wants to have into the rect * passed in as a parameter. All coordinates are relative to the widget's @@ -576,10 +564,6 @@ void CNxWidget::close(void) release(clickedWidget->getX(), clickedWidget->getY()); } - // Ensure the widget isn't running modally - - stopModal(); - if (m_parent != (CNxWidget *)NULL) { m_parent->closeChild(this); @@ -622,10 +606,6 @@ bool CNxWidget::hide(void) if (!m_flags.hidden) { m_flags.hidden = true; - - // Ensure the widget isn't running modally - - stopModal(); m_widgetEventHandlers->raiseHideEvent(); return true; } @@ -1398,39 +1378,6 @@ bool CNxWidget::removeChild(CNxWidget *widget) return false; } -/** - * Run the widget modally. - */ - -void CNxWidget::goModal(void) -{ - // Remember that we're running modally - - m_flags.modal = true; - - // Steal focus - - focus(); - - // Loop until no longer modal - - while (isModal()) - { - // Process pending events - - bool interestingEvent = m_widgetControl->pollEvents(this); - - // Did any interesting events occur? - - if (!interestingEvent) - { - // No, give up the CPU until something interesting happens. - - m_widgetControl->waitForModalEvent(); - } - } -} - /** * Get the child widget at the specified index. * diff --git a/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx b/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx index 9c0d67be3..5ecd8ab22 100644 --- a/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx +++ b/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx @@ -83,7 +83,6 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style) // Initialize state m_port = (CGraphicsPort *)NULL; - m_modal = false; m_haveGeometry = false; m_clickedWidget = (CNxWidget *)NULL; m_focusedWidget = (CNxWidget *)NULL; @@ -108,12 +107,15 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style) // Intialize semaphores: // - // m_modalSem. The semaphore that will wake up the modal loop on mouse or - // keypress events + // m_waitSem. The semaphore that will wake up the external logic on mouse events, + // keypress events, or widget deletion events. // m_geoSem. The semaphore that will synchronize window size and position - // informatin. + // information. - sem_init(&m_modalSem, 0, 0); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + m_waiting = false; + sem_init(&m_waitSem, 0, 0); +#endif #ifdef CONFIG_NX_MULTIUSER sem_init(&m_geoSem, 0, 0); #endif @@ -141,9 +143,12 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style) CWidgetControl::~CWidgetControl(void) { - // Stop any ongoing modal operation + // Notify any external waiters... this should not happen becaue it + // it is probably already too late - stopModal(); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + postWindowEvent(); +#endif // Delete any contained instances @@ -165,88 +170,69 @@ CWidgetControl::~CWidgetControl(void) } /** - * Run the widget modally. This will run the CWidgetControl - * application until stopModal() is called. - */ - -void CWidgetControl::goModal(void) -{ - // Enter modal - - m_modal = true; - - // Loop until stopModal() is called - - while (m_modal) - { - // Process pending events - - bool interestingEvent = pollEvents(); - - // Did any interesting events occur? - - if (!interestingEvent) - { - // No, give up the CPU until something interesting happens. - - waitForModalEvent(); - } - } -} - -/** - * Wait for an interesting modal event to occur (like a mouse or keyboard event) - */ - -void CWidgetControl::waitForModalEvent(void) -{ - // It would be an error if this were called outside of a modal loop - - if (m_modal) - { - // Wait for an interesting event (like a mouse or keyboard event) - - (void)sem_wait(&m_modalSem); - } -} - -/** - * Wake up the modal loop + * Wait for an interesting window event to occur (like a mouse or keyboard event). + * Caller's should exercise care to assure that the test for waiting and this + * call are "atomic" .. perhaps by locking the scheduler like: + * + * sched_lock(); + * ... + * if (no interesting events) + * { + * window->waitForWindowEvent(); + * } + * sched_unlock(); */ -void CWidgetControl::wakeupModalLoop(void) +#ifdef CONFIG_NXWIDGET_EVENTWAIT +void CWidgetControl::waitForWindowEvent(void) { - if (m_modal) - { - (void)sem_post(&m_modalSem); - } + m_waiting = true; + (void)sem_wait(&m_waitSem); + m_waiting = false; } +#endif /** - * Stop the widget running modally. + * Wake up external logic waiting for a window event */ -void CWidgetControl::stopModal(void) +#ifdef CONFIG_NXWIDGET_EVENTWAIT +void CWidgetControl::postWindowEvent(void) { - if (m_modal) + if (m_waiting) { - // No longer modal - - m_modal = false; - - // Wake up the modal loop so that it can terminate properly - - (void)sem_post(&m_modalSem); + (void)sem_post(&m_waitSem); } } +#endif /** * Run all code that needs to take place on a periodic basis. - * This is normally called from and is the main body of goModal() - * with widget == NULL. + * This method normally called externally... either periodically + * or when a window event is detected. If CONFIG_NXWIDGET_EVENTWAIT + * is defined, then external logic want call waitWindow event and + * when awakened, they chould call this function. As an example: + * + * for (;;) + * { + * sched_lock(); // Make the sequence atomic + * if (!window->pollEvents(0)) + * { + * window->waitWindowEvent(); + * } + * sched_unlock(); + * } + * + * This method is just a wrapper simply calls the following methods. + * It can easily be replace with custom, external logic. * - * @param widget Sub-widget to run, used for modal widgets; omit - * this parameter to run the whole system. + * processDeleteQueue() + * pollMouseEvents(widget) + * pollKeyboardEvents() + * pollCursorControlEvents() + * + * @param widget. Specific widget to poll. Use NULL to run the + * all widgets in the window. * @return True means some interesting event occurred */ @@ -316,7 +302,15 @@ void CWidgetControl::removeControlledWidget(CNxWidget *widget) void CWidgetControl::addToDeleteQueue(CNxWidget *widget) { + // Add the widget to the delete queue + m_deleteQueue.push_back(widget); + + // Then wake up logic that may be waiting for a window event + +#ifdef CONFIG_NXWIDGET_EVENTWAIT + postWindowEvent(); +#endif } /** @@ -422,6 +416,7 @@ void CWidgetControl::geometryEvent(NXHANDLE hWindow, giveGeoSem(); } + m_eventHandlers.raiseGeometryEvent(); sched_unlock(); } @@ -439,6 +434,7 @@ void CWidgetControl::redrawEvent(FAR const struct nxgl_rect_s *nxRect, bool more { CRect rect; rect.setNxRect(nxRect); + m_eventHandlers.raiseRedrawEvent(); } /** @@ -449,7 +445,8 @@ void CWidgetControl::redrawEvent(FAR const struct nxgl_rect_s *nxRect, bool more * @param pos The (x,y) position of the mouse. * @param buttons See NX_MOUSE_* definitions. */ - + +#ifdef CONFIG_NX_MOUSE void CWidgetControl::newMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t buttons) { // Save the mouse X/Y position @@ -569,10 +566,17 @@ void CWidgetControl::newMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t b } #endif - // Then wake up the modal loop + // Notify any external logic that a keyboard event has occurred + + m_eventHandlers.raiseMouseEvent(); - wakeupModalLoop(); + // Then wake up logic that may be waiting for a window event + +#ifdef CONFIG_NXWIDGET_EVENTWAIT + postWindowEvent(); +#endif } +#endif /** * This event is called from CCallback instance to provide notifications of @@ -582,7 +586,8 @@ void CWidgetControl::newMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t b * @param nCh The number of characters that are available in pStr[]. * @param pStr The array of characters. */ - + +#ifdef CONFIG_NX_KBD void CWidgetControl::newKeyboardEvent(uint8_t nCh, FAR const uint8_t *pStr) { FAR uint8_t *pBuffer = &m_kbdbuf[m_nCh]; @@ -596,10 +601,17 @@ void CWidgetControl::newKeyboardEvent(uint8_t nCh, FAR const uint8_t *pStr) *pBuffer++ = *pStr++; } - // Then wake up the modal loop + // Notify any external logic that a keyboard event has occurred + + m_eventHandlers.raiseKeyboardEvent(); + + // Then wake up logic that may be waiting for a window event - wakeupModalLoop(); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + postWindowEvent(); +#endif } +#endif /** * This event means that cursor control data is available for the window. @@ -617,9 +629,11 @@ void CWidgetControl::newCursorControlEvent(ECursorControl cursorControl) m_nCc++; } - // Then wake up the modal loop + // Then wake up logic that may be waiting for a window event - wakeupModalLoop(); +#ifdef CONFIG_NXWIDGET_EVENTWAIT + postWindowEvent(); +#endif } /** @@ -718,17 +732,16 @@ uint32_t CWidgetControl::elapsedTime(FAR const struct timespec *startTime) /** * Pass clicks to the widget hierarchy. If a single widget - * is supplied, only that widget is sent the click. That widget - * should be running modally. + * is supplied, only that widget is sent the click. * * @param x Click xcoordinate. * @param y Click ycoordinate. - * @param widget Pointer to a modally-running widget or NULL. + * @param widget Pointer to a specific widget or NULL. */ void CWidgetControl::handleLeftClick(nxgl_coord_t x, nxgl_coord_t y, CNxWidget *widget) { - // Working with a modal widget or the whole structure? + // Working with a specific widget or the whole structure? if (widget == (CNxWidget *)NULL) { @@ -769,8 +782,8 @@ void CWidgetControl::processDeleteQueue(void) /** * Process mouse/touchscreen events and send throughout the hierarchy. * - * @param widget to process, used for modal widgets; omit this parameter - * to run the whole system. + * @param widget. Specific widget to poll. Use NULL to run the + * all widgets in the window. * @return True means a mouse event occurred */ -- cgit v1.2.3