summaryrefslogtreecommitdiff
path: root/NxWidgets/nxwm
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-05-16 22:43:40 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-05-16 22:43:40 +0000
commit20958add7b2acc205e71569a3f318196baf7b7cf (patch)
tree5f479cc7c9a1bc538630ddaeae8c57b65b40e780 /NxWidgets/nxwm
parent6d8337323f1d60e7845a83508d4bbd1e0318ec3b (diff)
downloadnuttx-20958add7b2acc205e71569a3f318196baf7b7cf.tar.gz
nuttx-20958add7b2acc205e71569a3f318196baf7b7cf.tar.bz2
nuttx-20958add7b2acc205e71569a3f318196baf7b7cf.zip
NxWM: Add IApplicationFactory so that we can create multiple instances of applications; And, as a result of that, re-vamp entire threading model. this is now buggier than it was before
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4742 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'NxWidgets/nxwm')
-rw-r--r--NxWidgets/nxwm/doc/NxWM-ThreadingModel.pptbin0 -> 92672 bytes
-rw-r--r--NxWidgets/nxwm/include/capplicationwindow.hxx8
-rw-r--r--NxWidgets/nxwm/include/ccalibration.hxx40
-rw-r--r--NxWidgets/nxwm/include/cfullscreenwindow.hxx8
-rw-r--r--NxWidgets/nxwm/include/cnxconsole.hxx37
-rw-r--r--NxWidgets/nxwm/include/cstartwindow.hxx71
-rw-r--r--NxWidgets/nxwm/include/cwindowcontrol.hxx21
-rw-r--r--NxWidgets/nxwm/include/iapplication.hxx56
-rw-r--r--NxWidgets/nxwm/include/iapplicationwindow.hxx19
-rw-r--r--NxWidgets/nxwm/include/nxwmconfig.hxx50
-rw-r--r--NxWidgets/nxwm/src/capplicationwindow.cxx12
-rw-r--r--NxWidgets/nxwm/src/ccalibration.cxx74
-rw-r--r--NxWidgets/nxwm/src/cfullscreenwindow.cxx12
-rw-r--r--NxWidgets/nxwm/src/cnxconsole.cxx72
-rw-r--r--NxWidgets/nxwm/src/cstartwindow.cxx196
-rw-r--r--NxWidgets/nxwm/src/ctaskbar.cxx9
-rw-r--r--NxWidgets/nxwm/src/cwindowcontrol.cxx159
17 files changed, 760 insertions, 84 deletions
diff --git a/NxWidgets/nxwm/doc/NxWM-ThreadingModel.ppt b/NxWidgets/nxwm/doc/NxWM-ThreadingModel.ppt
new file mode 100644
index 000000000..382f69dd8
--- /dev/null
+++ b/NxWidgets/nxwm/doc/NxWM-ThreadingModel.ppt
Binary files differ
diff --git a/NxWidgets/nxwm/include/capplicationwindow.hxx b/NxWidgets/nxwm/include/capplicationwindow.hxx
index 8eda8d28a..f923f28b4 100644
--- a/NxWidgets/nxwm/include/capplicationwindow.hxx
+++ b/NxWidgets/nxwm/include/capplicationwindow.hxx
@@ -151,6 +151,14 @@ namespace NxWM
NXWidgets::INxWindow *getWindow(void) const;
/**
+ * Recover the contained window control
+ *
+ * @return. The window control used by this application
+ */
+
+ CWindowControl *getWindowControl(void) const ;
+
+ /**
* Set the window label
*
* @param appname. The name of the application to place on the window
diff --git a/NxWidgets/nxwm/include/ccalibration.hxx b/NxWidgets/nxwm/include/ccalibration.hxx
index 3d90d59a8..55cef6d84 100644
--- a/NxWidgets/nxwm/include/ccalibration.hxx
+++ b/NxWidgets/nxwm/include/ccalibration.hxx
@@ -314,6 +314,46 @@ namespace NxWM
bool isFullScreen(void) const;
};
+
+ class CCalibrationFactory : public IApplicationFactory
+ {
+ private:
+ CTaskbar *m_taskbar; /**< The taskbar */
+ CTouchscreen *m_touchscreen; /**< The touchscreen device */
+
+ public:
+ /**
+ * CCalibrationFactory Constructor
+ *
+ * @param taskbar. The taskbar instance used to terminate calibration
+ * @param touchscreen. An instance of the class that wraps the
+ * touchscreen device.
+ */
+
+ CCalibrationFactory(CTaskbar *taskbar, CTouchscreen *touchscreen);
+
+ /**
+ * CCalibrationFactory Destructor
+ */
+
+ inline ~CCalibrationFactory(void) { }
+
+ /**
+ * Create a new instance of an CCalibration (as IApplication).
+ */
+
+ IApplication *create(void);
+
+ /**
+ * Get the icon associated with the application
+ *
+ * @return An instance if IBitmap that may be used to rend the
+ * application's icon. This is an new IBitmap instance that must
+ * be deleted by the caller when it is no long needed.
+ */
+
+ NXWidgets::IBitmap *getIcon(void);
+ };
}
#endif // __INCLUDE_CCALIBRATION_HXX
diff --git a/NxWidgets/nxwm/include/cfullscreenwindow.hxx b/NxWidgets/nxwm/include/cfullscreenwindow.hxx
index 3c4117689..2e3fbd45d 100644
--- a/NxWidgets/nxwm/include/cfullscreenwindow.hxx
+++ b/NxWidgets/nxwm/include/cfullscreenwindow.hxx
@@ -115,6 +115,14 @@ namespace NxWM
NXWidgets::INxWindow *getWindow(void) const;
/**
+ * Recover the contained window control
+ *
+ * @return. The window control used by this application
+ */
+
+ CWindowControl *getWindowControl(void) const;
+
+ /**
* Set the window label
*
* @param appname. The name of the application to place on the window
diff --git a/NxWidgets/nxwm/include/cnxconsole.hxx b/NxWidgets/nxwm/include/cnxconsole.hxx
index 91fb941d8..b95c86406 100644
--- a/NxWidgets/nxwm/include/cnxconsole.hxx
+++ b/NxWidgets/nxwm/include/cnxconsole.hxx
@@ -191,6 +191,43 @@ namespace NxWM
bool isFullScreen(void) const;
};
+
+ class CNxConsoleFactory : public IApplicationFactory
+ {
+ private:
+ CTaskbar *m_taskbar; /**< The taskbar */
+
+ public:
+ /**
+ * CNxConsoleFactory Constructor
+ *
+ * @param taskbar. The taskbar instance used to terminate calibration
+ */
+
+ CNxConsoleFactory(CTaskbar *taskbar);
+
+ /**
+ * CNxConsoleFactory Destructor
+ */
+
+ inline ~CNxConsoleFactory(void) { }
+
+ /**
+ * Create a new instance of an CNxConsole (as IApplication).
+ */
+
+ IApplication *create(void);
+
+ /**
+ * Get the icon associated with the application
+ *
+ * @return An instance if IBitmap that may be used to rend the
+ * application's icon. This is an new IBitmap instance that must
+ * be deleted by the caller when it is no long needed.
+ */
+
+ NXWidgets::IBitmap *getIcon(void);
+ };
}
#endif // __cplusplus
diff --git a/NxWidgets/nxwm/include/cstartwindow.hxx b/NxWidgets/nxwm/include/cstartwindow.hxx
index d0ae5ec84..b0cad6127 100644
--- a/NxWidgets/nxwm/include/cstartwindow.hxx
+++ b/NxWidgets/nxwm/include/cstartwindow.hxx
@@ -42,6 +42,8 @@
#include <nuttx/config.h>
+#include <debug.h>
+
#include "tnxarray.hxx"
#include "iapplication.hxx"
@@ -59,8 +61,35 @@
namespace NxWM
{
+ /**
+ * Forward references
+ */
+
class CTaskbar;
+ /**
+ * Start window message opcodes and format
+ */
+
+ enum EStartWindowMessageOpcodes
+ {
+ MSGID_POSITIONAL_CHANGE = 1, /**< Change in window positional data (not used) */
+ MSGID_REDRAW_REQUEST, /**< Request to redraw a portion of the window (not used) */
+ MSGID_MOUSE_INPUT, /**< New mouse input is available */
+ MSGID_KEYBOARD_INPUT, /**< New keyboard input is available */
+ MSGID_DESTROY_APP /**< Destroy the application */
+ };
+
+ struct SStartWindowMessage
+ {
+ enum EStartWindowMessageOpcodes msgId; /**< The message opcode */
+ FAR void *instance; /**< Object instance. */
+ };
+
+ /**
+ * This class is the the start window application.
+ */
+
class CStartWindow : public IApplication,
private IApplicationCallback,
private NXWidgets::CWidgetEventHandler
@@ -72,7 +101,7 @@ namespace NxWM
struct SStartWindowSlot
{
- IApplication *app; /**< A reference to the icon */
+ IApplicationFactory *app; /**< A reference to the icon */
NXWidgets::CImage *image; /**< The icon image that goes with the application */
};
@@ -84,6 +113,33 @@ namespace NxWM
CApplicationWindow *m_window; /**< Reference to the application window */
TNxArray<struct SStartWindowSlot> 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
+ * the NX listener threads indirectly through this sequence:
+ *
+ * 1. 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.
+ * 2. 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.
+ * 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::CWindowControl.
+ * 6. NxWM::CWindowControl will send the a message on a well-known message
+ * queue.
+ * 7. This CStartWindow::startWindow task will receive and process that
+ * message.
+ */
+
+ static int startWindow(int argc, char *argv[]);
/**
* Called when the window minimize button is pressed.
@@ -107,7 +163,7 @@ namespace NxWM
* Stop all applications
*/
- void stopAllApplications(void);
+ void removeAllApplications(void);
/**
* Handle a widget action event. For CImage, this is a mouse button pre-release event.
@@ -202,18 +258,15 @@ namespace NxWM
* Add the application to the start window. The general sequence for
* setting up the start window is:
*
- * 1. Call CTaskBar::openApplicationWindow to create a window for the start window,
- * 2. Use the window to instantiate CStartWindow
- * 3. Call CStartWindow::addApplication numerous times to install applications
- * in the start window.
- * 4. Call CTaskBar::startApplication (initially minimized) to start the start
- * window application.
+ * 1. Call IAppicationFactory::create to a new instance of the application
+ * 2. Call CStartWindow::addApplication to add the application to the
+ * start window.
*
* @param app. The new application to add to the start window
* @return true on success
*/
- bool addApplication(IApplication *app);
+ bool addApplication(IApplicationFactory *app);
/**
* Simulate a mouse click on the icon at index. This inline method is only
diff --git a/NxWidgets/nxwm/include/cwindowcontrol.hxx b/NxWidgets/nxwm/include/cwindowcontrol.hxx
index acec12727..91e430c5c 100644
--- a/NxWidgets/nxwm/include/cwindowcontrol.hxx
+++ b/NxWidgets/nxwm/include/cwindowcontrol.hxx
@@ -43,6 +43,8 @@
#include <nuttx/config.h>
#include <sys/types.h>
+#include <mqueue.h>
+
#include <nuttx/nx/nxtk.h>
#include <nuttx/nx/nxconsole.h>
@@ -62,6 +64,12 @@
namespace NxWM
{
/**
+ * Forward references.
+ */
+
+ class IApplication;
+
+ /**
* The class CWindowControl integrates the widget control with some special
* handling of mouse and keyboard inputs neesed by NxWM
*/
@@ -70,6 +78,9 @@ namespace NxWM
private NXWidgets::CWindowEventHandler
{
private:
+ mqd_t m_mqd; /**< Message queue descriptor used to commincate with the
+ ** start window thread. */
+
/**
* Handle an NX window mouse input event.
*
@@ -105,6 +116,16 @@ namespace NxWM
*/
~CWindowControl(void);
+
+ /**
+ * Destroy the application window and everything in it. This is
+ * handled by CWindowControl (vs just calling the destructors) because
+ * in the case where an application destroys itself (because of pressing
+ * the stop button), then we need to unwind and get out of the application
+ * logic before destroying all of its objects.
+ */
+
+ void destroy(IApplication *app);
};
}
#endif // __cplusplus
diff --git a/NxWidgets/nxwm/include/iapplication.hxx b/NxWidgets/nxwm/include/iapplication.hxx
index 0d33db7bc..45067d900 100644
--- a/NxWidgets/nxwm/include/iapplication.hxx
+++ b/NxWidgets/nxwm/include/iapplication.hxx
@@ -44,6 +44,8 @@
#include "cnxstring.hxx"
#include "ibitmap.hxx"
+
+#include "cwindowcontrol.hxx"
#include "capplicationwindow.hxx"
/****************************************************************************
@@ -65,15 +67,26 @@ namespace NxWM
class IApplication
{
protected:
- // These values (and the accessors that go with them) violate the "purity"
- // of the base class. These are really part of the task bar implementation:
- // Each application provides this state information needed by the taskbar.
+ /**
+ * These values (and the accessors that go with them) violate the "purity"
+ * of the base class. These are really part of the task bar implementation:
+ * Each application provides this state information needed by the taskbar.
+ */
bool m_minimized; /**< True if the application is minimized */
bool m_topapp; /**< True if this application is at the top in the hiearchy */
public:
/**
+ * A virtual destructor is required in order to override the IApplication
+ * destructor. We do this because if we delete IApplication, we want the
+ * destructor of the class that inherits from IApplication to run, not this
+ * one.
+ */
+
+ virtual ~IApplication(void) { }
+
+ /**
* Each implementation of IApplication must provide a method to recover
* the contained CApplicationWindow instance.
*/
@@ -81,6 +94,18 @@ namespace NxWM
virtual IApplicationWindow *getWindow(void) const = 0;
/**
+ * Get the window widget control.
+ *
+ * @return The widget control of the underlying window instance.
+ */
+
+ virtual inline CWindowControl *getWindowControl(void) const
+ {
+ IApplicationWindow *window = getWindow();
+ return window->getWindowControl();
+ }
+
+ /**
* Get the icon associated with the application
*
* @return An instance if IBitmap that may be used to rend the
@@ -181,6 +206,31 @@ namespace NxWM
virtual bool isFullScreen(void) const = 0;
};
+
+ /**
+ * IApplicationFactory provides a mechanism for creating multiple instances
+ * of an application.
+ */
+
+ class IApplicationFactory
+ {
+ public:
+ /**
+ * Create a new instance of an application.
+ */
+
+ virtual IApplication *create(void) = 0;
+
+ /**
+ * Get the icon associated with the application
+ *
+ * @return An instance if IBitmap that may be used to rend the
+ * application's icon. This is an new IBitmap instance that must
+ * be deleted by the caller when it is no long needed.
+ */
+
+ virtual NXWidgets::IBitmap *getIcon(void) = 0;
+ };
}
#endif // __cplusplus
diff --git a/NxWidgets/nxwm/include/iapplicationwindow.hxx b/NxWidgets/nxwm/include/iapplicationwindow.hxx
index b00a03fa2..fe8830c2f 100644
--- a/NxWidgets/nxwm/include/iapplicationwindow.hxx
+++ b/NxWidgets/nxwm/include/iapplicationwindow.hxx
@@ -42,13 +42,10 @@
#include <nuttx/config.h>
-#include "cnxtkwindow.hxx"
-#include "cnxtoolbar.hxx"
-#include "cwidgeteventargs.hxx"
-#include "cwidgeteventhandler.hxx"
-#include "cimage.hxx"
-#include "clabel.hxx"
-#include "crlepalettebitmap.hxx"
+#include "inxwindow.hxx"
+#include "cnxstring.hxx"
+
+#include "cwindowcontrol.hxx"
/****************************************************************************
* Pre-Processor Definitions
@@ -122,6 +119,14 @@ namespace NxWM
virtual NXWidgets::INxWindow *getWindow(void) const = 0;
/**
+ * Recover the contained window control
+ *
+ * @return. The window control used by this application
+ */
+
+ virtual CWindowControl *getWindowControl(void) const = 0;
+
+ /**
* Set the window label
*
* @param appname. The name of the application to place on the window
diff --git a/NxWidgets/nxwm/include/nxwmconfig.hxx b/NxWidgets/nxwm/include/nxwmconfig.hxx
index 34721d777..3605f8c4f 100644
--- a/NxWidgets/nxwm/include/nxwmconfig.hxx
+++ b/NxWidgets/nxwm/include/nxwmconfig.hxx
@@ -263,6 +263,19 @@
* CONFIG_NXWM_STARTWINDOW_VSPACING - Vertical spacing. Default: 2 pixels
* CONFIG_NXWM_STARTWINDOW_HSPACING - Horizontal spacing. Default: 2 rows
* CONFIG_NXWM_STARTWINDOW_ICON - The glyph to use as the start window icon
+ * CONFIG_NXWM_STARTWINDOW_MQNAME - The well known name of the message queue
+ * Used to communicated from CWindowControl tothe start window thread.
+ * Default: "/dev/nxwm"
+ * CONFIG_NXWM_STARTWINDOW_MXMSGS - The maximum number of messages to queue
+ * before blocking. Defualt 32
+ * CONFIG_NXWM_STARTWINDOW_MXMPRIO - The message priority. Default: 42.
+ * CONFIG_NXWM_STARTWINDOW_PRIO - Priority of the NxConsole task. Default:
+ * SCHED_PRIORITY_DEFAULT. NOTE: This priority should be less than
+ * CONFIG_NXWIDGETS_SERVERPRIO or else there may be data overrun errors.
+ * Such errors would most likely appear as duplicated rows of data on the
+ * display.
+ * CONFIG_NXWM_STARTWINDOW_STACKSIZE - The stack size to use when starting the
+ * NxConsole task. Default: 2048 bytes.
*/
#ifndef CONFIG_NXWM_STARTWINDOW_VSPACING
@@ -281,6 +294,39 @@
# define CONFIG_NXWM_STARTWINDOW_ICON NxWM::g_playBitmap
#endif
+/**
+ * Start window task parameters
+ */
+
+#ifndef CONFIG_NXWM_STARTWINDOW_MQNAME
+# define CONFIG_NXWM_STARTWINDOW_MQNAME "/dev/nxwm"
+#endif
+
+#ifndef CONFIG_NXWM_STARTWINDOW_MXMSGS
+# ifdef CONFIG_NX_MXCLIENTMSGS
+# define CONFIG_NXWM_STARTWINDOW_MXMSGS CONFIG_NX_MXCLIENTMSGS
+# else
+# define CONFIG_NXWM_STARTWINDOW_MXMSGS 32
+# endif
+#endif
+
+#ifndef CONFIG_NXWM_STARTWINDOW_MXMPRIO
+# define CONFIG_NXWM_STARTWINDOW_MXMPRIO 42
+#endif
+
+#ifndef CONFIG_NXWM_STARTWINDOW_PRIO
+# define CONFIG_NXWM_STARTWINDOW_PRIO SCHED_PRIORITY_DEFAULT
+#endif
+
+#if CONFIG_NXWIDGETS_SERVERPRIO <= CONFIG_NXWM_STARTWINDOW_PRIO
+# warning "CONFIG_NXWIDGETS_SERVERPRIO <= CONFIG_NXWM_STARTWINDOW_PRIO"
+# warning" -- This can result in data overrun errors"
+#endif
+
+#ifndef CONFIG_NXWM_STARTWINDOW_STACKSIZE
+# define CONFIG_NXWM_STARTWINDOW_STACKSIZE 2048
+#endif
+
/* NxConsole Window *********************************************************/
/**
* NxConsole Window Configuration
@@ -347,7 +393,7 @@
* 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
+ * size. Default 1024
*/
#ifndef CONFIG_NXWM_TOUCHSCREEN_DEVNO
@@ -367,7 +413,7 @@
#endif
#ifndef CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK
-# define CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK 2048
+# define CONFIG_NXWM_TOUCHSCREEN_LISTENERSTACK 1024
#endif
/* Calibration display ******************************************************/
diff --git a/NxWidgets/nxwm/src/capplicationwindow.cxx b/NxWidgets/nxwm/src/capplicationwindow.cxx
index df8c69f11..15d4a4a9d 100644
--- a/NxWidgets/nxwm/src/capplicationwindow.cxx
+++ b/NxWidgets/nxwm/src/capplicationwindow.cxx
@@ -414,6 +414,18 @@ NXWidgets::INxWindow *CApplicationWindow::getWindow(void) const
}
/**
+ * Recover the contained window control
+ *
+ * @return. The window control used by this application
+ */
+
+CWindowControl *CApplicationWindow::getWindowControl(void) const
+{
+ NXWidgets::CWidgetControl *control = m_window->getWidgetControl();
+ return static_cast<CWindowControl*>(control);
+}
+
+/**
* Set the window label
*
* @param appname. The name of the application to place on the window
diff --git a/NxWidgets/nxwm/src/ccalibration.cxx b/NxWidgets/nxwm/src/ccalibration.cxx
index 2f9adb2e0..248aca838 100644
--- a/NxWidgets/nxwm/src/ccalibration.cxx
+++ b/NxWidgets/nxwm/src/ccalibration.cxx
@@ -1,5 +1,5 @@
/****************************************************************************
- * NxWidgets/nxwm/src/capplicationwindow.cxx
+ * NxWidgets/nxwm/src/ccalibration.cxx
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@@ -107,6 +107,11 @@ CCalibration::CCalibration(CTaskbar *taskbar, CFullScreenWindow *window,
CCalibration::~CCalibration(void)
{
+ // Make sure that the application is not running (it should already
+ // have been stopped)
+
+ stop();
+
// Although we did not create the window, the rule is that I have to dispose
// of it
@@ -788,4 +793,71 @@ bool CCalibration::createCalibrationData(struct SCalibrationData &data)
return true;
}
+/**
+ * CCalibrationFactory Constructor
+ *
+ * @param taskbar. The taskbar instance used to terminate calibration
+ * @param touchscreen. An instance of the class that wraps the
+ * touchscreen device.
+ */
+
+CCalibrationFactory::CCalibrationFactory(CTaskbar *taskbar, CTouchscreen *touchscreen)
+{
+ m_taskbar = taskbar;
+ m_touchscreen = touchscreen;
+}
+
+/**
+ * Create a new instance of an CCalibration (as IApplication).
+ */
+
+IApplication *CCalibrationFactory::create(void)
+{
+ // Call CTaskBar::openFullScreenWindow to create a full screen window for
+ // the calibation application
+
+ CFullScreenWindow *window = m_taskbar->openFullScreenWindow();
+ if (!window)
+ {
+ gdbg("ERROR: Failed to create CFullScreenWindow\n");
+ return (IApplication *)0;
+ }
+
+ // Open the window (it is hot in here)
+
+ if (!window->open())
+ {
+ gdbg("ERROR: Failed to open CFullScreenWindow \n");
+ delete window;
+ return (IApplication *)0;
+ }
+ // Instantiate the application, providing the window to the application's
+ // constructor
+
+ CCalibration *calibration = new CCalibration(m_taskbar, window, m_touchscreen);
+ if (!calibration)
+ {
+ gdbg("ERROR: Failed to instantiate CCalibration\n");
+ delete window;
+ return (IApplication *)0;
+ }
+
+ return static_cast<IApplication*>(calibration);
+}
+
+/**
+ * Get the icon associated with the application
+ *
+ * @return An instance if IBitmap that may be used to rend the
+ * application's icon. This is an new IBitmap instance that must
+ * be deleted by the caller when it is no long needed.
+ */
+
+NXWidgets::IBitmap *CCalibrationFactory::getIcon(void)
+{
+ NXWidgets::CRlePaletteBitmap *bitmap =
+ new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_CALIBRATION_ICON);
+
+ return bitmap;
+}
diff --git a/NxWidgets/nxwm/src/cfullscreenwindow.cxx b/NxWidgets/nxwm/src/cfullscreenwindow.cxx
index 7d63b02d7..40647d8e9 100644
--- a/NxWidgets/nxwm/src/cfullscreenwindow.cxx
+++ b/NxWidgets/nxwm/src/cfullscreenwindow.cxx
@@ -128,6 +128,18 @@ NXWidgets::INxWindow *CFullScreenWindow::getWindow(void) const
}
/**
+ * Recover the contained window control
+ *
+ * @return. The window control used by this application
+ */
+
+CWindowControl *CFullScreenWindow::getWindowControl(void) const
+{
+ NXWidgets::CWidgetControl *control = m_window->getWidgetControl();
+ return static_cast<CWindowControl*>(control);
+}
+
+/**
* Set the window label
*
* @param appname. The name of the application to place on the window
diff --git a/NxWidgets/nxwm/src/cnxconsole.cxx b/NxWidgets/nxwm/src/cnxconsole.cxx
index ec43c5656..577bf661e 100644
--- a/NxWidgets/nxwm/src/cnxconsole.cxx
+++ b/NxWidgets/nxwm/src/cnxconsole.cxx
@@ -47,6 +47,7 @@
#include <fcntl.h>
#include <semaphore.h>
#include <sched.h>
+#include <debug.h>
#include <apps/nsh.h>
@@ -141,6 +142,11 @@ CNxConsole::CNxConsole(CTaskbar *taskbar, CApplicationWindow *window)
CNxConsole::~CNxConsole(void)
{
+ // There would be a problem if we were stopped with the NxConsole task
+ // running... that should never happen but we'll check anyway:
+
+ stop();
+
// Although we didn't create it, we are responsible for deleting the
// application window
@@ -505,6 +511,72 @@ void CNxConsole::close(void)
}
/**
+ * CNxConsoleFactory Constructor
+ *
+ * @param taskbar. The taskbar instance used to terminate the console
+ */
+
+CNxConsoleFactory::CNxConsoleFactory(CTaskbar *taskbar)
+{
+ m_taskbar = taskbar;
+}
+
+/**
+ * Create a new instance of an CNxConsole (as IApplication).
+ */
+
+IApplication *CNxConsoleFactory::create(void)
+{
+ // Call CTaskBar::openFullScreenWindow to create a full screen window for
+ // the NxConsole application
+
+ CApplicationWindow *window = m_taskbar->openApplicationWindow();
+ if (!window)
+ {
+ gdbg("ERROR: Failed to create CApplicationWindow\n");
+ return (IApplication *)0;
+ }
+
+ // Open the window (it is hot in here)
+
+ if (!window->open())
+ {
+ gdbg("ERROR: Failed to open CApplicationWindow\n");
+ delete window;
+ return (IApplication *)0;
+ }
+
+ // Instantiate the application, providing the window to the application's
+ // constructor
+
+ CNxConsole *nxconsole = new CNxConsole(m_taskbar, window);
+ if (!nxconsole)
+ {
+ gdbg("ERROR: Failed to instantiate CNxConsole\n");
+ delete window;
+ return (IApplication *)0;
+ }
+
+ return static_cast<IApplication*>(nxconsole);
+}
+
+/**
+ * Get the icon associated with the application
+ *
+ * @return An instance if IBitmap that may be used to rend the
+ * application's icon. This is an new IBitmap instance that must
+ * be deleted by the caller when it is no long needed.
+ */
+
+NXWidgets::IBitmap *CNxConsoleFactory::getIcon(void)
+{
+ NXWidgets::CRlePaletteBitmap *bitmap =
+ new NXWidgets::CRlePaletteBitmap(&CONFIG_NXWM_NXCONSOLE_ICON);
+
+ return bitmap;
+}
+
+/**
* One time NSH initialization. This function must be called exactly
* once during the boot-up sequence to initialize the NSH library.
*
diff --git a/NxWidgets/nxwm/src/cstartwindow.cxx b/NxWidgets/nxwm/src/cstartwindow.cxx
index de35662d5..1c997fbb7 100644
--- a/NxWidgets/nxwm/src/cstartwindow.cxx
+++ b/NxWidgets/nxwm/src/cstartwindow.cxx
@@ -39,6 +39,13 @@
#include <nuttx/config.h>
+#include <cstdlib>
+#include <cfcntl>
+#include <csched>
+#include <cerrno>
+
+#include <mqueue.h>
+
#include "cwidgetcontrol.hxx"
#include "nxwmconfig.hxx"
@@ -51,7 +58,7 @@
********************************************************************************************/
/********************************************************************************************
- * CNxConsole Method Implementations
+ * CStartWindow Method Implementations
********************************************************************************************/
using namespace NxWM;
@@ -70,6 +77,10 @@ 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();
@@ -86,6 +97,11 @@ CStartWindow::CStartWindow(CTaskbar *taskbar, CApplicationWindow *window)
CStartWindow::~CStartWindow(void)
{
+ // There would be a problem if we were stopped with the start window task
+ // running... that should never happen but we'll check anyway:
+
+ stop();
+
// Although we didn't create it, we are responsible for deleting the
// application window
@@ -96,7 +112,7 @@ CStartWindow::~CStartWindow(void)
// Then stop and delete all applications
- stopAllApplications();
+ removeAllApplications();
}
/**
@@ -144,9 +160,24 @@ NXWidgets::CNxString CStartWindow::getName(void)
bool CStartWindow::run(void)
{
- // We don't have a thread of execution. We only respond to button presses
+ // Some sanity checking
- return true;
+ 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 const char **)0);
+
+ // Did we successfully start the NxConsole task?
+
+ return m_taskId >= 0;
}
/**
@@ -155,7 +186,20 @@ bool CStartWindow::run(void)
void CStartWindow::stop(void)
{
- // We don't have a thread of execution. We only respond to button presses
+ // 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);
+ }
}
/**
@@ -293,21 +337,17 @@ bool CStartWindow::isFullScreen(void) const
}
/**
- * Add the application to the start window. The general sequence for
- * setting up the start window is:
+ * Add the application to the start window. The general sequence is:
*
- * 1. Call CTaskBar::openApplicationWindow to create a window for the start window,
- * 2. Use the window to instantiate CStartWindow
- * 3. Call CStartWindow::addApplication numerous times to install applications
- * in the start window.
- * 4. Call CTaskBar::startApplication (initially minimized) to start the start
- * window application.
+ * 1. Call IAppicationFactory::create to a new instance of the application
+ * 2. Call CStartWindow::addApplication to add the application to the
+ * start window.
*
* @param app. The new application to add to the start window
* @return true on success
*/
-bool CStartWindow::addApplication(IApplication *app)
+bool CStartWindow::addApplication(IApplicationFactory *app)
{
// Recover the NXTK window instance contained in the application window
@@ -418,18 +458,17 @@ void CStartWindow::getIconBounds(void)
* Stop all applications
*/
-void CStartWindow::stopAllApplications(void)
+void CStartWindow::removeAllApplications(void)
{
- // Stop all applications and remove them from the task bar. 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
while (!m_slots.empty())
{
- // Stop the application (and remove it from the task bar)
+ // Remove the application factory from the start menu
- IApplication *app = m_slots.at(0).app;
- m_taskbar->stopApplication(app);
+ IApplicationFactory *app = m_slots.at(0).app;
// Now, delete the image and the application
@@ -459,12 +498,125 @@ void CStartWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
NXWidgets::CImage *image = m_slots.at(i).image;
if (image->isClicked())
{
- // Start a new copy of the application
+ // Create a new copy of the application
- m_taskbar->startApplication(m_slots.at(i).app, false);
+ IApplication *app = m_slots.at(i).app->create();
+ if (app)
+ {
+ // Start the new copy of the application
+
+ if (m_taskbar->startApplication(app, false))
+ {
+ // Then break out of the loop
+
+ break;
+ }
+ else
+ {
+ // If we cannot start the app. Destroy the
+ // instance we created and see what happens next.
+
+ CWindowControl *control = app->getWindowControl();
+ control->destroy(app);
+ }
+ }
+ }
+ }
+}
- // Then break out of the loop
+/**
+ * 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::CWindowControl.
+ * 6. NxWM::CWindowControl 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(CONFIG_NXWM_STARTWINDOW_MQNAME, O_RDONLY|O_CREAT, 0666, &attr);
+ if (mqd == (mqd_t)-1)
+ {
+ gdbg("ERROR: mq_open(%s) failed: %d\n", CONFIG_NXWM_STARTWINDOW_MQNAME, 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)
+ {
+ // EINTR is not an error. The wait was interrupted by a signal and
+ // we just need to try reading again.
+
+ if (errno != EINTR)
+ {
+ gdbg("ERROR: mq_receive failed: %d\n", errno);
+ }
+ }
+ while (nbytes < 0);
+
+ 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 ec3d8460b..ab686f81c 100644
--- a/NxWidgets/nxwm/src/ctaskbar.cxx
+++ b/NxWidgets/nxwm/src/ctaskbar.cxx
@@ -609,7 +609,9 @@ bool CTaskbar::stopApplication(IApplication *app)
hideApplicationWindow(app);
- // Stop the application (whatever this means to the application)
+ // Stop the application (whatever this means to the application). We
+ // separate stopping from destroying to get the application a chance
+ // to put things in order before being destroyed.
app->stop();
@@ -631,6 +633,11 @@ bool CTaskbar::stopApplication(IApplication *app)
}
}
+ // destroy the application
+
+ CWindowControl *control = app->getWindowControl();
+ control->destroy(app);
+
// Re-draw the new top, non-minimized application
bool ret = redrawTopWindow();
diff --git a/NxWidgets/nxwm/src/cwindowcontrol.cxx b/NxWidgets/nxwm/src/cwindowcontrol.cxx
index 841397a14..2c575d35b 100644
--- a/NxWidgets/nxwm/src/cwindowcontrol.cxx
+++ b/NxWidgets/nxwm/src/cwindowcontrol.cxx
@@ -36,9 +36,16 @@
/********************************************************************************************
* Included Files
********************************************************************************************/
-
+
#include <nuttx/config.h>
+#include <cfcntl>
+#include <cerrno>
+
+#include <debug.h>
+
+#include "nxwmconfig.hxx"
+#include "cstartwindow.hxx"
#include "cwindowcontrol.hxx"
/********************************************************************************************
@@ -62,6 +69,20 @@ using namespace NxWM;
CWindowControl::CWindowControl(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(CONFIG_NXWM_STARTWINDOW_MQNAME, O_WRONLY|O_CREAT, 0666, &attr);
+ if (m_mqd == (mqd_t)-1)
+ {
+ gdbg("ERROR: mq_open(%s) failed: %d\n", CONFIG_NXWM_STARTWINDOW_MQNAME, errno);
+ }
+
// Add ourself as the window callback
addWindowEventHandler(this);
@@ -73,12 +94,42 @@ CWindowControl::CWindowControl(FAR const NXWidgets::CWidgetStyle *style)
CWindowControl::~CWindowControl(void)
{
+ // Close the message queue
+
+ (void)mq_close(m_mqd);
+
// Remove ourself from the window callback
removeWindowEventHandler(this);
}
/**
+ * Destroy the application window and everything in it. This is
+ * handled by CWindowControl (vs just calling the destructors) because
+ * in the case where an application destroys itself (because of pressing
+ * the stop button), then we need to unwind and get out of the application
+ * logic before destroying all of its objects.
+ */
+
+void CWindowControl::destroy(IApplication *app)
+{
+ // Send a message to destroy the window isntance at a later time
+
+ struct SStartWindowMessage outmsg;
+ outmsg.msgId = MSGID_DESTROY_APP;
+ outmsg.instance = (FAR void *)app;
+
+ gdbg("Sending MSGID_DESTROY_APP with instance=%p\n", app);
+ int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
+ CONFIG_NXWM_STARTWINDOW_MXMPRIO);
+ if (ret < 0)
+ {
+ gdbg("ERROR: mq_send failed: %d\n", errno);
+ }
+
+}
+
+/**
* Handle an NX window mouse input event.
*
* @param e The event data.
@@ -89,24 +140,40 @@ void CWindowControl::handleMouseEvent(void)
{
// The logic path here is tortuous but flexible:
//
- // 1. A listener thread receives mouse input and injects that into NX
- // 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 mouse input
- // and send a message to the listener.
- // 4. The listener will call the NX message dispatcher will will do the
- // message callback.
- // 5. The callback goes into an instance of NXWidgets::CCallback that is
- // part of the CWidget control.
- // 6. That callback will update mouse information then raise the
- // mouse event,
- // 7. Which will finally call this function -- still running deep on the
- // stack in the listener thread.
- // 8. This function will then call back into the widget control to process
- // the mouse input.
-
- // Perform the poll
-
- pollEvents();
+ // 1. A listener thread receives mouse or touchscreen input and injects
+ // that into NX via nx_mousein
+ // 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 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
+ // 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
+ // 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::CWindowControl.
+ // 9. This NxWM::CWindowControl 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_MOUSE_INPUT;
+ outmsg.instance = (FAR void *)static_cast<CWidgetControl*>(this);
+
+ int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
+ CONFIG_NXWM_STARTWINDOW_MXMPRIO);
+ if (ret < 0)
+ {
+ gdbg("ERROR: mq_send failed: %d\n", errno);
+ }
}
#endif
@@ -119,25 +186,39 @@ void CWindowControl::handleKeyboardEvent(void)
{
// The logic path here is tortuous but flexible:
//
- // 1. A listener thread receives keyboard input and injects that into NX
- // 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 message to the listener.
- // 4. The listener will call the NX message dispatcher will will do the
- // message callback.
- // 5. The callback goes into an instance of NXWidgets::CCallback that is
- // part of the CWidget control.
- // 6. That callback will update keyboard information then raise the
- // keyboard event,
- // 7. Which will finally call this function -- still running deep on the
- // stack in the listener thread.
- // 8. This function will then call back into the widget control to process
- // the keyboard input.
-
- // Perform the poll
-
- pollEvents();
+ // 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::CWindowControl.
+ // 9. This NxWM::CWindowControl 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<CWidgetControl*>(this);
+
+ int ret = mq_send(m_mqd, &outmsg, sizeof(struct SStartWindowMessage),
+ CONFIG_NXWM_STARTWINDOW_MXMPRIO);
+ if (ret < 0)
+ {
+ gdbg("ERROR: mq_send failed: %d\n", errno);
+ }
}
#endif
-
-