📄 widget.c
字号:
// See if this is a pointer move or up message.
//
if((ulMessage == WIDGET_MSG_PTR_MOVE) || (ulMessage == WIDGET_MSG_PTR_UP))
{
//
// If there is not a widget that has captured pointer messages, then
// simply drop this message.
//
if(!g_pPointerWidget)
{
return(0);
}
//
// Send the message directly to the widget that has captured pointer
// messages.
//
ulRet = g_pPointerWidget->pfnMsgProc(g_pPointerWidget, ulMessage,
ulParam1, ulParam2);
//
// See if this is a pointer up message.
//
if(ulMessage == WIDGET_MSG_PTR_UP)
{
//
// Since this was a pointer up, the widget no longer has pointer
// messages captured.
//
g_pPointerWidget = 0;
}
//
// Return the value returned by the pointer capture widget.
//
return(ulRet);
}
//
// Loop through the tree under the widget until every widget is searched.
//
for(pTemp = pWidget; pTemp != pWidget->pParent; )
{
//
// See if this widget has a child.
//
if(pTemp->pChild)
{
//
// Go to this widget's child first.
//
pTemp = pTemp->pChild;
}
//
// This widget does not have a child, so either a sibling or a parent
// must be checked. When moving back to the parent, another move must
// be performed as well to avoid getting stuck in a loop (since the
// parent's children have already been searched.
//
else
{
//
// Loop until returning to the parent of the starting widget. This
// loop will be explicitly broken out of if an intervening widget
// is encountered that has not been searched.
//
while(pTemp != pWidget->pParent)
{
//
// Send the message to this widget.
//
ulRet = pTemp->pfnMsgProc(pTemp, ulMessage, ulParam1,
ulParam2);
//
// If this is a pointer down message, the widget accepted the
// message and the handler didn't modify the tree such that
// this widget is no longer present, then save a pointer to the
// widget for subsequent pointer move or pointer up messages.
//
if((ulMessage == WIDGET_MSG_PTR_DOWN) && (ulRet != 0))
{
//
// Is the current widget still in the tree?
//
if(WidgetIsInTree(&g_sRoot, pTemp))
{
//
// The widget is still in the tree so save it for later
// use.
//
g_pPointerWidget = pTemp;
}
else
{
//
// Although this widget handled the PTR_DOWN message,
// it's message handler rearranged the widget tree and
// removed itself so we don't want to send any more
// messages directly to it after all.
//
g_pPointerWidget = 0;
}
}
//
// If the widget returned success and the search should stop on
// success then return immediately.
//
if((ulRet != 0) && bStopOnSuccess)
{
return(ulRet);
}
//
// See if this widget has a sibling.
//
if(pTemp->pNext)
{
//
// Visit the sibling of this widget.
//
pTemp = pTemp->pNext;
//
// Since this widget has not been searched yet, break out
// of the controlling loop.
//
break;
}
else
{
//
// This widget has no siblings, so go to its parent. Since
// the parent has already been searched, the same sibling
// vs. parent decision must be made on this widget as well.
//
pTemp = pTemp->pParent;
}
}
}
}
//
// No widget returned success for the message, or bStopOnSuccess was zero,
// so return zero.
//
return(0);
}
//*****************************************************************************
//
//! Adds a message to the widget message queue.
//!
//! \param pWidget is the widget to which the message should be sent.
//! \param ulMessage is the message to be sent.
//! \param ulParam1 is the first parameter to the message.
//! \param ulParam2 is the second parameter to the message.
//! \param bPostOrder is \b true if the message should be sent via a post-order
//! search, and \b false if it should be sent via a pre-order search.
//! \param bStopOnSuccess is \b true if the message should be sent to widgets
//! until one returns success, and \b false if it should be sent to all
//! widgets.
//!
//! This function places a widget message into the message queue for later
//! processing. The messages are removed from the queue by
//! WidgetMessageQueueProcess() and sent to the appropriate place.
//!
//! It is safe for code which interrupts WidgetMessageQueueProcess() (or called
//! by it) to call this function to send a message. It is not safe for code
//! which interrupts this function to call this function as well; it is up to
//! the caller to guarantee that the later sequence never occurs.
//!
//! \return Returns 1 if the message was added to the queue, and 0 if it could
//! not be added since either the queue is full or another context is currently
//! adding a message to the queue.
//
//*****************************************************************************
long
WidgetMessageQueueAdd(tWidget *pWidget, unsigned long ulMessage,
unsigned long ulParam1, unsigned long ulParam2,
unsigned long bPostOrder, unsigned long bStopOnSuccess)
{
unsigned long ulNext;
unsigned long ulOwned;
//
// Check the arguments.
//
ASSERT(pWidget);
//
// Get the mutex we use to protect access to the message queue.
//
ulOwned = WidgetMutexGet(&g_ucMQMutex);
if(ulOwned)
{
//
// The mutex is already being held by some other caller so return a
// failure.
//
#ifdef DEBUG_MSGQ
g_ulMQMutexClash++;
#endif
return(0);
}
//
// Compute the next value for the write pointer.
//
ulNext = (g_ulMQWrite + 1) % QUEUE_SIZE;
//
// If the queue is not empty, and this is a pointer move message, see if
// the previous message was also a move and, if so, replace the
// coordinates. Without this, the message queue can very quickly overflow
// if the application is busy doing something while the user keeps pressing
// the display.
//
if(ulMessage == WIDGET_MSG_PTR_MOVE)
{
//
// Is the message queue empty?
//
if(g_ulMQRead != g_ulMQWrite)
{
//
// No - what is the index of the previous message?
//
ulOwned = (g_ulMQWrite == 0) ? (QUEUE_SIZE - 1) : (g_ulMQWrite - 1);
//
// Was this a pointer move message?
//
if(g_pMQ[g_ulMQWrite].ulMessage == WIDGET_MSG_PTR_MOVE)
{
//
// Yes - overwrite this message with the new
// coordinate information.
//
g_pMQ[ulOwned].ulParam1 = ulParam1;
g_pMQ[ulOwned].ulParam2 = ulParam2;
#ifdef DEBUG_MSGQ
g_ulMQMoveOverwrite++;
#endif
//
// Release the message queue mutex.
//
WidgetMutexPut(&g_ucMQMutex);
//
// Success.
//
return(1);
}
}
}
//
// Return a failure if the message queue is full.
//
if(ulNext == g_ulMQRead)
{
#ifdef DEBUG_MSGQ
g_ulMQOverflow++;
if(ulMessage != WIDGET_MSG_PTR_MOVE)
{
g_ulMQNonMouseOverflow++;
g_ulMQLastLostMsg = ulMessage;
}
#endif
//
// Release the message queue mutex.
//
WidgetMutexPut(&g_ucMQMutex);
return(0);
}
//
// Write this message into the next location in the message queue.
//
g_pMQ[g_ulMQWrite].ulFlags = ((bPostOrder ? MQ_FLAG_POST_ORDER : 0) |
(bStopOnSuccess ? MQ_FLAG_STOP_ON_SUCCESS :
0));
g_pMQ[g_ulMQWrite].pWidget = pWidget;
g_pMQ[g_ulMQWrite].ulMessage = ulMessage;
g_pMQ[g_ulMQWrite].ulParam1 = ulParam1;
g_pMQ[g_ulMQWrite].ulParam2 = ulParam2;
//
// Update the message queue write pointer.
//
g_ulMQWrite = ulNext;
//
// Release the message queue mutex.
//
WidgetMutexPut(&g_ucMQMutex);
//
// Success.
//
return(1);
}
//*****************************************************************************
//
//! Processes the messages in the widget message queue.
//!
//! This function extracts messages from the widget message queue one at a time
//! and processes them. If the processing of a widget message requires that a
//! new message be sent, it is acceptable to call WidgetMessageQueueAdd(). It
//! is also acceptable for code which interrupts this function to call
//! WidgetMessageQueueAdd() to send more messages. In both cases, the newly
//! added message will also be processed before this function returns.
//!
//! \return None.
//
//*****************************************************************************
void
WidgetMessageQueueProcess(void)
{
tWidget *pWidget;
unsigned long ulFlags, ulMessage, ulParam1, ulParam2;
//
// Loop while there are more messages in the message queue.
//
while(g_ulMQRead != g_ulMQWrite)
{
//
// Copy the contents of this message into local variables.
//
pWidget = g_pMQ[g_ulMQRead].pWidget;
ulFlags = g_pMQ[g_ulMQRead].ulFlags;
ulMessage = g_pMQ[g_ulMQRead].ulMessage;
ulParam1 = g_pMQ[g_ulMQRead].ulParam1;
ulParam2 = g_pMQ[g_ulMQRead].ulParam2;
//
// Remove this message from the queue.
//
g_ulMQRead = (g_ulMQRead + 1) % QUEUE_SIZE;
//
// See if this message should be sent via a post-order or pre-order
// search.
//
if(ulFlags & MQ_FLAG_POST_ORDER)
{
//
// Send this message with a post-order search of the widget tree.
//
WidgetMessageSendPostOrder(pWidget, ulMessage, ulParam1, ulParam2,
((ulFlags & MQ_FLAG_STOP_ON_SUCCESS) ?
1 : 0));
}
else
{
//
// Send this message with a pre-order search of the widget tree.
//
WidgetMessageSendPreOrder(pWidget, ulMessage, ulParam1, ulParam2,
((ulFlags & MQ_FLAG_STOP_ON_SUCCESS) ?
1 : 0));
}
}
}
//*****************************************************************************
//
//! Sends a pointer message.
//!
//! \param ulMessage is the pointer message to be sent.
//! \param lX is the X coordinate associated with the message.
//! \param lY is the Y coordinate associated with the message.
//!
//! This function sends a pointer message to the root widget. A pointer driver
//! (such as a touch screen driver) can use this function to deliver pointer
//! activity to the widget tree without having to have direct knowledge of the
//! structure of the widget framework.
//!
//! \return Returns 1 if the message was added to the queue, and 0 if it could
//! not be added since the queue is full.
//
//*****************************************************************************
long
WidgetPointerMessage(unsigned long ulMessage, long lX, long lY)
{
//
// Add the message to the widget message queue.
//
return(WidgetMessageQueueAdd(WIDGET_ROOT, ulMessage, lX, lY, 1, 1));
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -