From a63f8bb684d01a23bfe1ee85b1d7faf983b9d1ea Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 28 Feb 2013 18:48:11 +0000 Subject: NxWidgets/NxWM updates from Petteri Aimonen (Patches 0007-0013) git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5689 42af7a65-404d-4744-a932-0658087f49c3 --- NxWidgets/ChangeLog.txt | 48 ++++++- NxWidgets/Kconfig | 24 ++++ NxWidgets/libnxwidgets/include/cimage.hxx | 8 +- NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx | 71 +++++++--- NxWidgets/libnxwidgets/src/cimage.cxx | 27 ++-- NxWidgets/libnxwidgets/src/cmultilinetextbox.cxx | 4 +- NxWidgets/libnxwidgets/src/cnxtimer.cxx | 8 +- NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx | 46 +++++-- NxWidgets/nxwm/include/cstartwindow.hxx | 1 - NxWidgets/nxwm/include/cwindowmessenger.hxx | 25 +++- NxWidgets/nxwm/src/capplicationwindow.cxx | 22 +++- NxWidgets/nxwm/src/cstartwindow.cxx | 153 +--------------------- NxWidgets/nxwm/src/ctaskbar.cxx | 18 ++- NxWidgets/nxwm/src/cwindowmessenger.cxx | 116 +++++++--------- 14 files changed, 286 insertions(+), 285 deletions(-) (limited to 'NxWidgets') diff --git a/NxWidgets/ChangeLog.txt b/NxWidgets/ChangeLog.txt index dd3422dcc..1d2abab4d 100644 --- a/NxWidgets/ChangeLog.txt +++ b/NxWidgets/ChangeLog.txt @@ -280,4 +280,50 @@ it works with indexed input images. * NxWidgets::CLabel: Fix backward conditional compilation in the "flicker free" logic. - +* NxWidgets::CNxTimer: Previously repeated timers were re-enabled after + the timer action event. Consequently, if the action event handler tried + to stop the timer, the request would be ignored. Changes the order + so that the timer is re-enabled before the callback. There is still + no risk of re-entrancy, because everything executes on the USRWORK work + queue. From Petteri Aimonen. +* NxWidgets::CMultiLineTestBox: Fix text placement error. From Petteri + Aimonen. +* NxWidgets::CWidgetControl: Added another semaphore, boundssem, which + is set as soon as the screen bounds are known. This corrects two + problems: + 1) Due to the way nxgl_rectsize computes the size, it will never + be 0,0 like CWidgetControl expects. Therefore the size is considered + valid even though it has not been set yet. + 2) After the check is fixed to test for > 1, NxWM window creation will + hang. This is due to the fact that it uses the screen bounds for + determining window size. This was being blocked on geosem, which + is only posted after the size has been set. + From Petteri Aimonen. +* NxWidgets::CImage: Two enhancements: + 1) Allow changing the bitmap even after the control has been created. + 2) Allow giving 'null' to have the control draw no image at all. + From Petteri Aimonen. +* NxWM::CTaskBar: Allow windows with null icon. This makes sense for e.g. + full screen windows. From Petteri Aimonen. +* NxWM::CApplicationWindow: Add config options to override NxWM + stop/minimize icons. From Petteri Aimonen. +* NwWM::CStartWindow, NxWM::CWindowMessenger: Get rid of the start window + thread. Instead, handle all events through the USRWORK work queue. + For me, this was necessary because I would open some files in button + handlers and close them in NxTimer handlers. If these belonged to + different tasks, the close operation would fail. Further benefits: + + Gets rid of one task and message queue. + + Reduces the amount of code required + + Decouples CStartWindow from everything else - now it is just a window + with application icons, not an integral part of the event logic. + + All events come from the same thread, which reduces the possibility of + multithreading errors in user code. + + The user code can also send events to USRWORK, so that everything gets + serialized nicely without having to use so many mutexes. + Drawbacks: + - Currently the work state structure is malloc()ed, causing one allocation + and free per each input event. Could add a memory pool for these later, but + the speed difference doesn't seem noticeable. + - The work queue will add ~50 ms latency to input events. This is however + configurable, and the delay is anyway short enough that it is unnoticeable. + From Petteri Aimonen. diff --git a/NxWidgets/Kconfig b/NxWidgets/Kconfig index 656399199..6f5f3e924 100644 --- a/NxWidgets/Kconfig +++ b/NxWidgets/Kconfig @@ -463,6 +463,30 @@ config NXWM_BACKGROUND_IMAGE The name of the image to use in the background window. Default: NXWidgets::g_nuttxBitmap +comment "Application Window Configuration" + +config NXWM_CUSTOM_APPWINDOW_ICONS + bool "Custom Start/Stop Application Window Icons" + default n + ---help--- + Select to override the default Application Window Stop and Minimize Icons. + +if NXWM_CUSTOM_APPWINDOW_ICONS + +config NXWM_STOP_BITMAP + string "Stop Icon" + default "NxWM::g_stopBitmap" + ---help--- + The glyph to use as the Stop icon. Default: NxWM::g_stopBitmap + +config NXWM_MINIMIZE_BITMAP + string "Minimize Icon" + default "NxWM::g_minimizeBitmap" + ---help--- + The glyph to use as the Minimize icon. Default: NxWM::g_minimizeBitmap + +endif + comment "Start Window Configuration" comment "Horizontal and vertical spacing of icons in the task bar" diff --git a/NxWidgets/libnxwidgets/include/cimage.hxx b/NxWidgets/libnxwidgets/include/cimage.hxx index 6093c5f33..438ea7267 100644 --- a/NxWidgets/libnxwidgets/include/cimage.hxx +++ b/NxWidgets/libnxwidgets/include/cimage.hxx @@ -1,7 +1,7 @@ /**************************************************************************** * NxWidgets/libnxwidgets/include/cimage.hxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -207,6 +207,12 @@ namespace NXWidgets inline FAR IBitmap *getBitmap() const { return m_bitmap; } + /** + * Set the bitmap that this image contains. + */ + + inline void setBitmap(FAR IBitmap *bitmap) { m_bitmap = bitmap; } + /** * Insert the dimensions that this widget wants to have into the rect * passed in as a parameter. All coordinates are relative to the diff --git a/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx b/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx index e709271a0..f0afe2c47 100644 --- a/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx +++ b/NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx @@ -1,7 +1,7 @@ /**************************************************************************** * NxWidgets/libnxwidgets/include/cwidgetcontrol.hxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -39,11 +39,12 @@ /**************************************************************************** * Included Files ****************************************************************************/ - + #include #include #include +#include #include #include @@ -203,6 +204,7 @@ namespace NXWidgets struct nxgl_rect_s m_bounds; /**< Size of the display */ #ifdef CONFIG_NX_MULTIUSER sem_t m_geoSem; /**< Posted when geometry is valid */ + sem_t m_boundsSem; /**< Posted when bounds are valid */ #endif CWindowEventHandlerList m_eventHandlers; /**< List of event handlers. */ @@ -228,7 +230,7 @@ namespace NXWidgets * @param startTime A time in the past from which to compute the elapsed time. * @return The elapsed time since startTime */ - + uint32_t elapsedTime(FAR const struct timespec *startTime); /** @@ -256,7 +258,7 @@ namespace NXWidgets /** * Delete any widgets in the deletion queue. */ - + void processDeleteQueue(void); /** @@ -324,6 +326,37 @@ namespace NXWidgets giveGeoSem(); } + /** + * Take the bounds semaphore (handling signal interruptions) + */ + +#ifdef CONFIG_NX_MULTIUSER + void takeBoundsSem(void); +#else + inline void takeBoundsSem(void) {} +#endif + + /** + * Give the bounds semaphore + */ + + inline void giveBoundsSem(void) + { +#ifdef CONFIG_NX_MULTIUSER + sem_post(&m_boundsSem); +#endif + } + + /** + * Wait for bounds data + */ + + inline void waitBoundsData(void) + { + takeBoundsSem(); + giveBoundsSem(); + } + /** * Clear all mouse events */ @@ -345,7 +378,7 @@ namespace NXWidgets /** * Destructor. */ - + virtual ~CWidgetControl(void); /** @@ -407,7 +440,7 @@ namespace NXWidgets * all widgets in the window. * @return True means some interesting event occurred */ - + bool pollEvents(CNxWidget *widget = (CNxWidget *)NULL); /** @@ -425,7 +458,7 @@ namespace NXWidgets * * @param widget The widget to be controlled. */ - + inline void addControlledWidget(CNxWidget* widget) { m_widgets.push_back(widget); @@ -438,7 +471,7 @@ namespace NXWidgets */ void removeControlledWidget(CNxWidget* widget); - + /** * Get the number of controlled widgets. * @@ -456,7 +489,7 @@ namespace NXWidgets * * @param widget The widget to add to the delete queue. */ - + void addToDeleteQueue(CNxWidget *widget); /** @@ -469,7 +502,7 @@ namespace NXWidgets void setClickedWidget(CNxWidget *widget); /** - * Get the clicked widget pointer. + * Get the clicked widget pointer. * * @return Pointer to the clicked widget. */ @@ -502,7 +535,7 @@ namespace NXWidgets } /** - * Get the focused widget pointer. + * Get the focused widget pointer. * * @return Pointer to the focused widget. */ @@ -513,7 +546,7 @@ namespace NXWidgets } /** - * Check for the occurrence of a double click. + * Check for the occurrence of a double click. * * @return Pointer to the clicked widget. */ @@ -582,7 +615,7 @@ namespace NXWidgets * @param pos The (x,y) position of the mouse. * @param buttons See NX_MOUSE_* definitions. */ - + void newMouseEvent(FAR const struct nxgl_point_s *pos, uint8_t buttons); /** @@ -624,7 +657,7 @@ namespace NXWidgets * * @param cursorControl The cursor control code received. */ - + void newCursorControlEvent(ECursorControl cursorControl); /** @@ -639,21 +672,21 @@ namespace NXWidgets } /** - * Get the window bounding box in physical display coordinated. This - * method may need to wait until geometry data is available. + * Get the window bounding box in physical display coordinates. This + * method may need to wait until bounds data is available. * * @return This function returns the window handle. */ inline CRect getWindowBoundingBox(void) { - waitGeoData(); + waitBoundsData(); return CRect(&m_bounds); } inline void getWindowBoundingBox(FAR struct nxgl_rect_s *bounds) { - waitGeoData(); + waitBoundsData(); nxgl_rectcopy(bounds, &m_bounds); } @@ -759,7 +792,7 @@ namespace NXWidgets inline void removeWindowEventHandler(CWindowEventHandler *eventHandler) { - m_eventHandlers.removeWindowEventHandler(eventHandler); + m_eventHandlers.removeWindowEventHandler(eventHandler); } }; } diff --git a/NxWidgets/libnxwidgets/src/cimage.cxx b/NxWidgets/libnxwidgets/src/cimage.cxx index 30bf7e78b..9b3137129 100644 --- a/NxWidgets/libnxwidgets/src/cimage.cxx +++ b/NxWidgets/libnxwidgets/src/cimage.cxx @@ -1,7 +1,7 @@ /**************************************************************************** * NxWidgets/libnxwidgets/include/cimage.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -88,7 +88,7 @@ /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ - + /**************************************************************************** * Method Implementations ****************************************************************************/ @@ -163,6 +163,13 @@ void CImage::getPreferredDimensions(CRect &rect) const void CImage::drawContents(CGraphicsPort *port) { + if (!m_bitmap) + { + // No image to draw + + return; + } + // Get the the drawable region CRect rect; @@ -187,11 +194,11 @@ void CImage::drawContents(CGraphicsPort *port) m_bitmap->setSelected(isClicked() || m_highlighted); // This is the number of rows that we can draw at the top of the display - + nxgl_coord_t nTopRows = m_bitmap->getHeight() - m_origin.y; if (nTopRows > rect.getHeight()) { - nTopRows = rect.getHeight(); + nTopRows = rect.getHeight(); } else if (nTopRows < 0) { @@ -214,7 +221,7 @@ void CImage::drawContents(CGraphicsPort *port) // the display nxgl_coord_t nLeftPixels = m_bitmap->getWidth() - m_origin.x; - + // This is the number of rows that we have to pad on the right if the display // width is wider than the image width @@ -257,7 +264,7 @@ void CImage::drawContents(CGraphicsPort *port) // Replace any transparent pixels with the background color. // Then we can use the faster opaque drawBitmap() function. - + ptr = buffer; for (int i = 0; i < nLeftPixels; i++, ptr++) { @@ -337,12 +344,12 @@ void CImage::drawBorder(CGraphicsPort *port) { return; } - + // Work out which colors to use nxgl_coord_t color1; nxgl_coord_t color2; - + if (isClicked()) { // Bevelled into the screen @@ -357,7 +364,7 @@ void CImage::drawBorder(CGraphicsPort *port) color1 = getShineEdgeColor(); color2 = getShadowEdgeColor(); } - + port->drawBevelledRect(getX(), getY(), getWidth(), getHeight(), color1, color2); } @@ -389,7 +396,7 @@ void CImage::onClick(nxgl_coord_t x, nxgl_coord_t y) } /** - * Raises an action. + * Raises an action. * * @param x The x coordinate of the mouse. * @param y The y coordinate of the mouse. diff --git a/NxWidgets/libnxwidgets/src/cmultilinetextbox.cxx b/NxWidgets/libnxwidgets/src/cmultilinetextbox.cxx index 94caac5fd..df060f037 100644 --- a/NxWidgets/libnxwidgets/src/cmultilinetextbox.cxx +++ b/NxWidgets/libnxwidgets/src/cmultilinetextbox.cxx @@ -1261,8 +1261,8 @@ void CMultiLineTextBox::drawRow(CGraphicsPort *port, int row) uint8_t rowLength = m_text->getLineTrimmedLength(row); struct nxgl_point_s pos; - pos.x = getRowX(row) + m_canvasX; - pos.y = getRowY(row) + m_canvasY; + pos.x = getRowX(row) + m_canvasX + rect.getX(); + pos.y = getRowY(row) + m_canvasY + rect.getY(); // Determine the background and text color diff --git a/NxWidgets/libnxwidgets/src/cnxtimer.cxx b/NxWidgets/libnxwidgets/src/cnxtimer.cxx index d663df036..d67cee6e8 100644 --- a/NxWidgets/libnxwidgets/src/cnxtimer.cxx +++ b/NxWidgets/libnxwidgets/src/cnxtimer.cxx @@ -193,16 +193,16 @@ void CNxTimer::workQueueCallback(FAR void *arg) This->m_isRunning = false; - // Raise the action event. - - This->m_widgetEventHandlers->raiseActionEvent(); - // Restart the timer if this is a repeating timer if (This->m_isRepeater) { This->start(); } + + // Raise the action event. + + This->m_widgetEventHandlers->raiseActionEvent(); } diff --git a/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx b/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx index 644abd714..2cb1a930d 100644 --- a/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx +++ b/NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx @@ -1,7 +1,7 @@ /**************************************************************************** * NxWidgets/libnxwidgets/src/cwidgetcontrol.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -117,6 +117,7 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style) sem_init(&m_waitSem, 0, 0); #endif #ifdef CONFIG_NX_MULTIUSER + sem_init(&m_boundsSem, 0, 0); sem_init(&m_geoSem, 0, 0); #endif @@ -135,12 +136,11 @@ CWidgetControl::CWidgetControl(FAR const CWidgetStyle *style) copyWidgetStyle(&m_style, style); } } - /** * Destructor. */ - + CWidgetControl::~CWidgetControl(void) { // Notify any external waiters... this should not happen because it @@ -235,7 +235,7 @@ void CWidgetControl::postWindowEvent(void) * all widgets in the window. * @return True means some interesting event occurred */ - + bool CWidgetControl::pollEvents(CNxWidget *widget) { // Delete any queued widgets @@ -299,7 +299,7 @@ void CWidgetControl::removeControlledWidget(CNxWidget *widget) * * @param widget The widget to add to the delete queue. */ - + void CWidgetControl::addToDeleteQueue(CNxWidget *widget) { // Add the widget to the delete queue @@ -330,7 +330,7 @@ void CWidgetControl::setClickedWidget(CNxWidget *widget) m_clickedWidget->release(m_clickedWidget->getX() - 10, 0); } - + // Update the pointer m_clickedWidget = widget; @@ -394,18 +394,19 @@ void CWidgetControl::geometryEvent(NXHANDLE hWindow, if (!m_hWindow) { // Save one-time server specific information - + m_hWindow = hWindow; nxgl_rectcopy(&m_bounds, bounds); + giveBoundsSem(); } // In the normal start up sequence, the window is created with zero size // at position 0,0. The safe thing to do is to set the position (still // with size 0, then then set the size. Assuming that is what is being // done, we will not report that we have valid geometry until the size - // becomes nonzero. + // becomes nonzero (or actually over 1). - if (!m_haveGeometry && size->h > 0 && size->w > 0) + if (!m_haveGeometry && size->h > 1 && size->w > 1) { // Wake up any threads waiting for initial position information. // REVISIT: If the window is moved or repositioned, then the @@ -619,7 +620,7 @@ void CWidgetControl::newKeyboardEvent(uint8_t nCh, FAR const uint8_t *pStr) * * @param cursorControl The cursor control code received. */ - + void CWidgetControl::newCursorControlEvent(ECursorControl cursorControl) { // Append the new cursor control @@ -688,7 +689,7 @@ void CWidgetControl::copyWidgetStyle(CWidgetStyle *dest, const CWidgetStyle *src * @param tp A time in the past from which to compute the elapsed time. * @return The elapsed time since tp */ - + uint32_t CWidgetControl::elapsedTime(FAR const struct timespec *startTime) { struct timespec endTime; @@ -701,7 +702,7 @@ uint32_t CWidgetControl::elapsedTime(FAR const struct timespec *startTime) uint32_t seconds = endTime.tv_sec - startTime->tv_sec; // Get the elapsed nanoseconds, borrowing from the seconds if necessary - + int32_t endNanoSeconds = endTime.tv_nsec; if (startTime->tv_nsec > endNanoSeconds) { @@ -767,7 +768,7 @@ void CWidgetControl::handleLeftClick(nxgl_coord_t x, nxgl_coord_t y, CNxWidget * /** * Delete any widgets in the deletion queue. */ - + void CWidgetControl::processDeleteQueue(void) { int i = 0; @@ -916,6 +917,25 @@ void CWidgetControl::takeGeoSem(void) } #endif +/** + * Take the bounds semaphore (handling signal interruptions) + */ + +#ifdef CONFIG_NX_MULTIUSER +void CWidgetControl::takeBoundsSem(void) +{ + // Take the bounds semaphore. Retry is an error occurs (only if + // the error is due to a signal interruption). + + int ret; + do + { + ret = sem_wait(&m_boundsSem); + } + while (ret < 0 && errno == EINTR); +} +#endif + /** * Clear all mouse events */ diff --git a/NxWidgets/nxwm/include/cstartwindow.hxx b/NxWidgets/nxwm/include/cstartwindow.hxx index 52a67fbd4..250d5068c 100644 --- a/NxWidgets/nxwm/include/cstartwindow.hxx +++ b/NxWidgets/nxwm/include/cstartwindow.hxx @@ -119,7 +119,6 @@ namespace NxWM CApplicationWindow *m_window; /**< Reference to the application window */ TNxArray m_slots; /**< List of apps in the start window */ struct nxgl_size_s m_iconSize; /**< A box big enough to hold the largest icon */ - pid_t m_taskId; /**< ID of the start window task */ /** * This is the start window task. This function receives window events from diff --git a/NxWidgets/nxwm/include/cwindowmessenger.hxx b/NxWidgets/nxwm/include/cwindowmessenger.hxx index 11a48645b..a30010fd8 100644 --- a/NxWidgets/nxwm/include/cwindowmessenger.hxx +++ b/NxWidgets/nxwm/include/cwindowmessenger.hxx @@ -1,7 +1,7 @@ /**************************************************************************** * NxWidgets/nxwm/include/cwindowmessenger.hxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -39,12 +39,12 @@ /**************************************************************************** * Included Files ****************************************************************************/ - + #include #include -#include +#include #include #include @@ -83,9 +83,20 @@ namespace NxWM public NXWidgets::CWidgetControl { private: - mqd_t m_mqd; /**< Message queue descriptor used to commincate with the - ** start window thread. */ - + /** Structure that stores data for the work queue callback. */ + + struct work_state_t + { + work_s work; + CWindowMessenger *windowMessenger; + void *instance; + }; + + /** Work queue callback functions */ + + static void inputWorkCallback(FAR void *arg); + static void destroyWorkCallback(FAR void *arg); + /** * Handle an NX window mouse input event. * @@ -109,7 +120,7 @@ namespace NxWM * * @param arg - User provided argument (see nx_block or nxtk_block) */ - + void handleBlockedEvent(FAR void *arg); public: diff --git a/NxWidgets/nxwm/src/capplicationwindow.cxx b/NxWidgets/nxwm/src/capplicationwindow.cxx index d2e044298..77d196d07 100644 --- a/NxWidgets/nxwm/src/capplicationwindow.cxx +++ b/NxWidgets/nxwm/src/capplicationwindow.cxx @@ -1,7 +1,7 @@ /******************************************************************************************** * NxWidgets/nxwm/src/capplicationwindow.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -54,6 +54,18 @@ * Pre-Processor Definitions ********************************************************************************************/ +#ifdef CONFIG_NXWM_STOP_BITMAP +extern const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_STOP_BITMAP; +#else +# define CONFIG_NXWM_STOP_BITMAP g_stopBitmap +#endif + +#ifdef CONFIG_NXWM_MINIMIZE_BITMAP +extern const struct NXWidgets::SRlePaletteBitmap CONFIG_NXWM_MINIMIZE_BITMAP; +#else +# define CONFIG_NXWM_MINIMIZE_BITMAP g_minimizeBitmap +#endif + /******************************************************************************************** * CApplicationWindow Method Implementations ********************************************************************************************/ @@ -192,7 +204,7 @@ bool CApplicationWindow::open(void) { // Create STOP bitmap container - m_stopBitmap = new NXWidgets::CRlePaletteBitmap(&g_stopBitmap); + m_stopBitmap = new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_STOP_BITMAP); if (!m_stopBitmap) { return false; @@ -244,7 +256,7 @@ bool CApplicationWindow::open(void) #ifndef CONFIG_NXWM_DISABLE_MINIMIZE // Create MINIMIZE application bitmap container - m_minimizeBitmap = new NXWidgets::CRlePaletteBitmap(&g_minimizeBitmap); + m_minimizeBitmap = new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_MINIMIZE_BITMAP); if (!m_minimizeBitmap) { return false; @@ -375,7 +387,7 @@ void CApplicationWindow::redraw(void) m_minimizeImage->redraw(); m_minimizeImage->setRaisesEvents(true); } - + // And finally draw the window label m_windowLabel->enableDrawing(); @@ -406,7 +418,7 @@ void CApplicationWindow::hide(void) m_minimizeImage->disableDrawing(); m_minimizeImage->setRaisesEvents(false); } - + // Disable the window label m_windowLabel->disableDrawing(); diff --git a/NxWidgets/nxwm/src/cstartwindow.cxx b/NxWidgets/nxwm/src/cstartwindow.cxx index bc7b747f8..1b56094ec 100644 --- a/NxWidgets/nxwm/src/cstartwindow.cxx +++ b/NxWidgets/nxwm/src/cstartwindow.cxx @@ -1,7 +1,7 @@ /******************************************************************************************** * NxWidgets/nxwm/src/cstartwindow.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -44,8 +44,6 @@ #include #include -#include - #include "cwidgetcontrol.hxx" #include "nxwmconfig.hxx" @@ -66,7 +64,7 @@ */ FAR const char *NxWM::g_startWindowMqName = CONFIG_NXWM_STARTWINDOW_MQNAME; - + /******************************************************************************************** * CStartWindow Method Implementations ********************************************************************************************/ @@ -89,10 +87,6 @@ CStartWindow::CStartWindow(CTaskbar *taskbar, CApplicationWindow *window) m_taskbar = taskbar; m_window = window; - // The start window task is not running - - m_taskId = -1; - // Add our personalized window label NXWidgets::CNxString myName = getName(); @@ -169,24 +163,7 @@ NXWidgets::CNxString CStartWindow::getName(void) bool CStartWindow::run(void) { - // Some sanity checking - - if (m_taskId >= 0) - { - // The start window task is already running??? - - return false; - } - - // Start the start window task - - m_taskId = TASK_CREATE("StartWindow", CONFIG_NXWM_STARTWINDOW_PRIO, - CONFIG_NXWM_STARTWINDOW_STACKSIZE, startWindow, - (FAR char * const *)0); - - // Did we successfully start the NxConsole task? - - return m_taskId >= 0; + return true; } /** @@ -195,21 +172,8 @@ bool CStartWindow::run(void) void CStartWindow::stop(void) { - // Delete the start window task --- what are we doing? This should never - // happen because the start window task is persistent! - - if (m_taskId >= 0) - { - // Call task_delete(), possibly stranding resources - - pid_t pid = m_taskId; - m_taskId = -1; - - // Then delete the NSH task - - task_delete(pid); - } } + /** * Destroy the application and free all of its resources. This method * will initiate blocking of messages from the NX server. The server @@ -532,7 +496,7 @@ void CStartWindow::getIconBounds(void) void CStartWindow::removeAllApplications(void) { - // Stop all applications and remove them from the start window. Clearly, there + // Stop all applications and remove them from the start window. Clearly, there // are some ordering issues here... On an orderly system shutdown, disconnection // should really occur priority to deleting instances @@ -543,7 +507,7 @@ void CStartWindow::removeAllApplications(void) IApplicationFactory *app = m_slots.at(0).app; // Now, delete the image and the application - + delete app; delete m_slots.at(0).image; @@ -596,108 +560,3 @@ void CStartWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) } } -/** - * This is the start window task. This function receives window events from - * the NX listener threads indirectly through this sequence: - * - * 1. NX listener thread receives a windows event. This may be a - * positional change notification, a redraw request, or mouse or - * keyboard input. - * 2. The NX listener thread performs the callback by calling a - * NXWidgets::CCallback method associated with the window. - * 3. NXWidgets::CCallback calls into NXWidgets::CWidgetControl to process - * the event. - * 4. NXWidgets::CWidgetControl records the new state data and raises a - * window event. - * 5. NXWidgets::CWindowEventHandlerList will give the event to - * NxWM::CWindowMessenger. - * 6. NxWM::CWindowMessenger will send the a message on a well-known message - * queue. - * 7. This CStartWindow::startWindow task will receive and process that - * message. - */ - -int CStartWindow::startWindow(int argc, char *argv[]) -{ - /* Open a well-known message queue for reading */ - - struct mq_attr attr; - attr.mq_maxmsg = CONFIG_NXWM_STARTWINDOW_MXMSGS; - attr.mq_msgsize = sizeof(struct SStartWindowMessage); - attr.mq_flags = 0; - - mqd_t mqd = mq_open(g_startWindowMqName, O_RDONLY|O_CREAT, 0666, &attr); - if (mqd == (mqd_t)-1) - { - gdbg("ERROR: mq_open(%s) failed: %d\n", g_startWindowMqName, errno); - return EXIT_FAILURE; - } - - // Now loop forever, receiving and processing messages. Ultimately, all - // widget driven events (button presses, etc.) are driven by this logic - // on this thread. - - for (;;) - { - // Receive the next message - - struct SStartWindowMessage msg; - ssize_t nbytes = mq_receive(mqd, &msg, sizeof(struct SStartWindowMessage), 0); - if (nbytes < 0) - { - int errval = errno; - - // EINTR is not an error. The wait was interrupted by a signal and - // we just need to try reading again. - - if (errval != EINTR) - { - gdbg("ERROR: mq_receive failed: %d\n", errval); - } - else - { - gdbg("mq_receive interrupted by signal\n"); - } - - continue; - } - - gvdbg("Received msgid=%d nbytes=%d\n", msg.msgId, nbytes); - DEBUGASSERT(nbytes = sizeof(struct SStartWindowMessage) && msg.instance); - - // Dispatch the message to the appropriate CWidgetControl and to the - // appropriate CWidgetControl method - - switch (msg.msgId) - { - break; - - case MSGID_MOUSE_INPUT: // New mouse input is available - case MSGID_KEYBOARD_INPUT: // New keyboard input is available - { - // Handle all new window input events by calling the CWidgetControl::pollEvents() method - - NXWidgets::CWidgetControl *control = (NXWidgets::CWidgetControl *)msg.instance; - control->pollEvents(); - } - break; - - case MSGID_DESTROY_APP: // Destroy the application - { - // Handle all destroy application events - - gdbg("Deleting app=%p\n", msg.instance); - IApplication *app = (IApplication *)msg.instance; - delete app; - } - break; - - case MSGID_POSITIONAL_CHANGE: // Change in window positional data (not used) - case MSGID_REDRAW_REQUEST: // Request to redraw a portion of the window (not used) - default: - gdbg("ERROR: Unrecognized or unsupported msgId: %d\n", (int)msg.msgId); - break; - } - } -} - diff --git a/NxWidgets/nxwm/src/ctaskbar.cxx b/NxWidgets/nxwm/src/ctaskbar.cxx index 031edbf3a..93c38ed98 100644 --- a/NxWidgets/nxwm/src/ctaskbar.cxx +++ b/NxWidgets/nxwm/src/ctaskbar.cxx @@ -1,7 +1,7 @@ /******************************************************************************************** * NxWidgets/nxwm/src/ctaskbar.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -456,11 +456,21 @@ bool CTaskbar::startApplication(IApplication *app, bool minimized) NXWidgets::IBitmap *bitmap = app->getIcon(); - // Create a CImage instance to manage the applications icon + // Create a CImage instance to manage the applications icon. Assume the + // minimum size in case no bitmap is provided (bitmap == NULL) + + int w = 1; + int h = 1; + + if (bitmap) + { + w = bitmap->getWidth(); + h = bitmap->getHeight(); + } NXWidgets::CImage *image = - new NXWidgets::CImage(control, 0, 0, bitmap->getWidth(), - bitmap->getHeight(), bitmap, 0); + new NXWidgets::CImage(control, 0, 0, w, h, bitmap, 0); + if (!image) { return false; diff --git a/NxWidgets/nxwm/src/cwindowmessenger.cxx b/NxWidgets/nxwm/src/cwindowmessenger.cxx index 032dd1bf2..114690838 100644 --- a/NxWidgets/nxwm/src/cwindowmessenger.cxx +++ b/NxWidgets/nxwm/src/cwindowmessenger.cxx @@ -1,7 +1,7 @@ /******************************************************************************************** * NxWidgets/nxwm/src/cwindowmessenger.cxx * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -69,20 +69,6 @@ using namespace NxWM; CWindowMessenger::CWindowMessenger(FAR const NXWidgets::CWidgetStyle *style) : NXWidgets::CWidgetControl(style) { - // Open a message queue to communicate with the start window task. We need to create - // the message queue if it does not exist. - - struct mq_attr attr; - attr.mq_maxmsg = CONFIG_NXWM_STARTWINDOW_MXMSGS; - attr.mq_msgsize = sizeof(struct SStartWindowMessage); - attr.mq_flags = 0; - - m_mqd = mq_open(g_startWindowMqName, O_WRONLY|O_CREAT, 0666, &attr); - if (m_mqd == (mqd_t)-1) - { - gdbg("ERROR: mq_open(%s) failed: %d\n", g_startWindowMqName, errno); - } - // Add ourself to the list of window event handlers addWindowEventHandler(this); @@ -97,10 +83,6 @@ CWindowMessenger::~CWindowMessenger(void) // Remove ourself from the list of the window event handlers removeWindowEventHandler(this); - - // Close the message queue - - (void)mq_close(m_mqd); } /** @@ -120,8 +102,8 @@ void CWindowMessenger::handleMouseEvent(void) // 3. The NX server will determine which window gets the mouse input // and send a window event message to the NX listener thread. // 4. The NX listener thread receives a windows event. The NX listener thread - // which is part of CTaskBar and was created when NX server connection was - // established). This event may be a positional change notification, a + // is part of CTaskBar and was created when NX server connection was + // established. This event may be a positional change notification, a // redraw request, or mouse or keyboard input. In this case, mouse input. // 5. The NX listener thread handles the message by calling nx_eventhandler(). // nx_eventhandler() dispatches the message by calling a method in the @@ -133,20 +115,18 @@ void CWindowMessenger::handleMouseEvent(void) // window event. // 8. NXWidgets::CWindowEventHandlerList will give the event to this method // NxWM::CWindowMessenger. - // 9. This NxWM::CWindowMessenger method will send the a message on a well- - // known message queue. - // 10. This CStartWindow::startWindow task will receive and process that - // message by calling CWidgetControl::pollEvents() + // 9. This NxWM::CWindowMessenger method will schedule an entry on the work + // queue. + // 10. The work queue callback will finally call pollEvents() to execute whatever + // actions the input event should trigger. - struct SStartWindowMessage outmsg; - outmsg.msgId = MSGID_MOUSE_INPUT; - outmsg.instance = (FAR void *)static_cast(this); + work_state_t *state = new work_state_t; + state->windowMessenger = this; - int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage), - CONFIG_NXWM_STARTWINDOW_MXMPRIO); + int ret = work_queue(USRWORK, &state->work, &inputWorkCallback, state, 0); if (ret < 0) { - gdbg("ERROR: mq_send failed: %d\n", errno); + gdbg("ERROR: work_queue failed: %d\n", ret); } } #endif @@ -158,41 +138,13 @@ void CWindowMessenger::handleMouseEvent(void) #ifdef CONFIG_NX_KBD void CWindowMessenger::handleKeyboardEvent(void) { - // The logic path here is tortuous but flexible: - // - // 1. A listener thread receives keyboard input and injects that into NX - // via nx_kbdin. - // 2. In the multi-user mode, this will send a message to the NX server - // 3. The NX server will determine which window gets the keyboard input - // and send a window event message to the NX listener thread. - // 4. The NX listener thread receives a windows event. The NX listener thread - // which is part of CTaskBar and was created when NX server connection was - // established). This event may be a positional change notification, a - // redraw request, or mouse or keyboard input. In this case, keyboard input. - // 5. The NX listener thread handles the message by calling nx_eventhandler(). - // nx_eventhandler() dispatches the message by calling a method in the - // NXWidgets::CCallback instance associated with the window. - // NXWidgets::CCallback is a part of the CWidgetControl. - // 6. NXWidgets::CCallback calls into NXWidgets::CWidgetControl to process - // the event. - // 7. NXWidgets::CWidgetControl records the new state data and raises a - // window event. - // 8. NXWidgets::CWindowEventHandlerList will give the event to this method - // NxWM::CWindowMessenger. - // 9. This NxWM::CWindowMessenger method will send the a message on a well- - // known message queue. - // 10. This CStartWindow::startWindow task will receive and process that - // message by calling CWidgetControl::pollEvents() - - struct SStartWindowMessage outmsg; - outmsg.msgId = MSGID_KEYBOARD_INPUT; - outmsg.instance = (FAR void *)static_cast(this); + work_state_t *state = new work_state_t; + state->windowMessenger = this; - int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage), - CONFIG_NXWM_STARTWINDOW_MXMPRIO); + int ret = work_queue(USRWORK, &state->work, &inputWorkCallback, state, 0); if (ret < 0) { - gdbg("ERROR: mq_send failed: %d\n", errno); + gdbg("ERROR: work_queue failed: %d\n", ret); } } #endif @@ -213,18 +165,40 @@ void CWindowMessenger::handleKeyboardEvent(void) void CWindowMessenger::handleBlockedEvent(FAR void *arg) { - // Send a message to destroy the window isntance at a later time + // Send a message to destroy the window instance. - struct SStartWindowMessage outmsg; - outmsg.msgId = MSGID_DESTROY_APP; - outmsg.instance = arg; + work_state_t *state = new work_state_t; + state->windowMessenger = this; + state->instance = arg; - gdbg("Sending MSGID_DESTROY_APP with instance=%p\n", arg); - int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage), - CONFIG_NXWM_STARTWINDOW_MXMPRIO); + int ret = work_queue(USRWORK, &state->work, &destroyWorkCallback, state, 0); if (ret < 0) { - gdbg("ERROR: mq_send failed: %d\n", errno); + gdbg("ERROR: work_queue failed: %d\n", ret); } } +/** Work queue callback functions */ + +void CWindowMessenger::inputWorkCallback(FAR void *arg) +{ + work_state_t *state = (work_state_t*)arg; + state->windowMessenger->pollEvents(); + delete state; +} + +void CWindowMessenger::destroyWorkCallback(FAR void *arg) +{ + work_state_t *state = (work_state_t*)arg; + + // First make sure any pending input events have been handled. + + state->windowMessenger->pollEvents(); + + // Then release the memory. + + gdbg("Deleting app=%p\n", state->instance); + IApplication *app = (IApplication *)state->instance; + delete app; + delete state; +} -- cgit v1.2.3