From 20958add7b2acc205e71569a3f318196baf7b7cf Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 16 May 2012 22:43:40 +0000 Subject: 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 --- NxWidgets/nxwm/src/cwindowcontrol.cxx | 159 +++++++++++++++++++++++++--------- 1 file changed, 120 insertions(+), 39 deletions(-) (limited to 'NxWidgets/nxwm/src/cwindowcontrol.cxx') 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 +#include +#include + +#include + +#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,11 +94,41 @@ 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. * @@ -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(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(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 - - -- cgit v1.2.3