📄 wm.c
字号:
if ((pWin->cb != NULL) && (Status & WM_SF_ISVIS))
{
WM_MESSAGE Msg;
WM__PaintCallbackCnt++;
if (Status & WM_SF_LATE_CLIP)
{
Msg.hWin = hWin;
Msg.MsgId = WM_PAINT;
Msg.Data.p = (GUI_RECT *) &pWin->InvalidRect;
WM_SetDefault();
WM_SendMessage(hWin, &Msg);
}
else
{
WM_ITERATE_START(&pWin->InvalidRect)
{
Msg.hWin = hWin;
Msg.MsgId = WM_PAINT;
Msg.Data.p = (GUI_RECT *) &pWin->InvalidRect;
WM_SetDefault();
WM_SendMessage(hWin, &Msg);
} WM_ITERATE_END();
}
WM__PaintCallbackCnt--;
}
}
/*********************************************************************
*
* _Paint1Trans
*
* Purpose:
* Draw a transparent window as part of an other one (the active window: pAWin).
* This is required because transparent windows are drawn as part of their
* non-transparent parents.
* Return value:
* 0 if nothing was drawn (no invalid rect)
* 1 if something was drawn (invalid rect exists)
* Add. info:
* It is important to restore the modified settings, especially the invalid rectangle
* of the window. The invalid rectangle needs to be set, as it is passed as add. info
* to the callback on WM_PAINT.
* On traditional transparent windows, the transparent window is never drawn on its own,
* so there is no need to restore the invalid rectangle.
* However, with WM_SF_CONST_OUTLINE, the window itself may need to be redrawn because it
* can be invalid. Modifying the invalid rectangle would lead to not updating the window
* in the worst case.
*/
#if WM_SUPPORT_TRANSPARENCY
static int _Paint1Trans(WM_HWIN hWin, WM_Obj *pWin)
{
int xPrev, yPrev;
WM_Obj* pAWin = WM_H2P(GUI_Context.hAWin);
/* Check if we need to do any drawing */
if (GUI_RectsIntersect(&pAWin->InvalidRect, &pWin->Rect))
{
/* Save old values */
xPrev = GUI_Context.xOff;
yPrev = GUI_Context.yOff;
/* Set values for the current (transparent) window, rather than the one below */
GUI__IntersectRects(&pWin->InvalidRect, &pWin->Rect, &pAWin->InvalidRect);
WM__hATransWindow = hWin;
GUI_Context.xOff = pWin->Rect.x0;
GUI_Context.yOff = pWin->Rect.y0;
/* Do the actual drawing ... */
_Paint1(hWin, pWin);
/* Restore settings */
WM__hATransWindow = 0;
GUI_Context.xOff = xPrev;
GUI_Context.yOff = yPrev;
return 1; /* Some drawing took place */
}
return 0; /* No invalid area, so nothing was drawn */
}
#endif
/*********************************************************************
*
* _PaintTransChildren
*
* Purpose:
* Paint transparent children. This function is obviously required
* only if there are transparent windows.
* Function: Obvious
* Parameter: Obvious
* Returns: ---
*/
#if WM_SUPPORT_TRANSPARENCY
static void _PaintTransChildren(WM_Obj *pWin)
{
WM_HWIN hChild;
WM_Obj* pChild;
if (pWin->Status & WM_SF_ISVIS)
{
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext)
{
pChild = WM_H2P(hChild);
if ((pChild->Status & (WM_SF_HASTRANS | WM_SF_ISVIS)) /* Transparent & visible ? */ == (WM_SF_HASTRANS | WM_SF_ISVIS))
{
/* Set invalid area of the window to draw */
if (GUI_RectsIntersect(&pChild->Rect, &pWin->InvalidRect))
{
GUI_RECT InvalidRectPrev;
InvalidRectPrev = pWin->InvalidRect;
if (_Paint1Trans(hChild, pChild))
{
_PaintTransChildren(pChild);
}
pWin->InvalidRect = InvalidRectPrev;
}
}
}
}
}
#endif
/*********************************************************************
*
* _PaintTransTopSiblings
*
* Purpose:
* Paint transparent top siblings. This function is obviously required
* only if there are transparent windows.
* Function: Obvious
* Parameter: Obvious
* Returns: ---
*/
#if WM_SUPPORT_TRANSPARENCY
static void _PaintTransTopSiblings(WM_HWIN hWin, WM_Obj *pWin)
{
WM_HWIN hParent;
WM_Obj* pParent;
hParent = pWin->hParent;
hWin = pWin->hNext;
while (hParent)
{
/* Go hierarchy up to desktop window */
for (; hWin; hWin = pWin->hNext)
{
pWin = WM_H2P(hWin);
/* paint window if it is transparent & visible */
if ((pWin->Status & (WM_SF_HASTRANS | WM_SF_ISVIS)) == (WM_SF_HASTRANS | WM_SF_ISVIS))
{
_Paint1Trans(hWin, pWin);
}
/* paint transparent & visible children */
_PaintTransChildren(pWin);
}
pParent = WM_H2P(hParent);
hWin = pParent->hNext;
hParent = pParent->hParent;
}
}
#endif
/*********************************************************************
*
* Callback for Paint message
*
* This callback is used by the window manger in conjunction with
* banding memory devices. A pointer to this routine is given to
* the banding memory device. This callback in turn will send the
* paint message to the window.
*
**********************************************************************
*/
/*********************************************************************
*
* WM__PaintWinAndOverlays
*
* Purpose
* Paint the given window and all overlaying windows
* (transparent children and transparent top siblings)
*/
void WM__PaintWinAndOverlays(WM_PAINTINFO *pInfo)
{
WM_HWIN hWin;
WM_Obj* pWin;
hWin = pInfo->hWin;
pWin = pInfo->pWin;
#if WM_SUPPORT_TRANSPARENCY
/* Transparent windows without const outline are drawn as part of the background and can be skipped. */
if ((pWin->Status & (WM_SF_HASTRANS | WM_SF_CONST_OUTLINE)) != WM_SF_HASTRANS)
{
#endif
_Paint1(hWin, pWin); /* Draw the window itself */
#if WM_SUPPORT_TRANSPARENCY
}
if (WM__TransWindowCnt != 0)
{
_PaintTransChildren(pWin); /* Draw all transparent children */
_PaintTransTopSiblings(hWin, pWin); /* Draw all transparent top level siblings */
}
#endif
}
/*********************************************************************
*
* _cbPaintMemDev
*
* Purpose:
* This is the routine called by the banding memory device. It calls
* the same _cbPaint Routine which is also used when drawing directly;
* the only add. work done is adjustment of the invalid rectangle.
* This way the invalid rectangle visible by the window callback function
* is limited to the current band, allowing the callback to optimize
* better.
*/
#if GUI_SUPPORT_MEMDEV
static void _cbPaintMemDev(void *p)
{
GUI_RECT Rect;
WM_Obj* pWin = WM_H2P(GUI_Context.hAWin);
Rect = pWin->InvalidRect;
pWin->InvalidRect = GUI_Context.ClipRect;
WM__PaintWinAndOverlays((WM_PAINTINFO *) p);
pWin->InvalidRect = Rect;
}
#endif
/*********************************************************************
*
* _Paint
Returns:
1: a window has been redrawn
0: No window has been drawn
*/
static int _Paint(WM_HWIN hWin, WM_Obj *pWin)
{
int Ret = 0;
if (pWin->Status & WM_SF_INVALID)
{
if (pWin->cb)
{
if (WM__ClipAtParentBorders(&pWin->InvalidRect, hWin))
{
WM_PAINTINFO Info;
Info.hWin = hWin;
Info.pWin = pWin;
WM_SelectWindow(hWin);
#if GUI_SUPPORT_MEMDEV
if (pWin->Status & WM_SF_MEMDEV)
{
int Flags;
GUI_RECT r = pWin->InvalidRect;
Flags = (pWin->Status & WM_SF_HASTRANS) ? GUI_MEMDEV_HASTRANS : GUI_MEMDEV_NOTRANS;
/*
* Currently we treat a desktop window as transparent, because per default it does not repaint itself.
*/
if (pWin->hParent == 0)
{
Flags = GUI_MEMDEV_HASTRANS;
}
GUI_MEMDEV_Draw(&r, _cbPaintMemDev, &Info, 0, Flags);
}
else
#endif
{
WM__PaintWinAndOverlays(&Info);
Ret = 1; /* Something has been done */
}
}
}
/* We purposly clear the invalid flag after painting so we can still query the invalid rectangle while painting */
pWin->Status &= ~WM_SF_INVALID; /* Clear invalid flag */
if (pWin->Status & WM_CF_MEMDEV_ON_REDRAW)
{
pWin->Status |= WM_CF_MEMDEV;
}
WM__NumInvalidWindows--;
}
return Ret; /* Nothing done */
}
/*********************************************************************
*
* _DrawNext
*/
static void _DrawNext(void)
{
int UpdateRem = 1;
WM_HWIN iWin = (NextDrawWin == WM_HWIN_NULL) ? WM__FirstWin : NextDrawWin;
GUI_CONTEXT ContextOld;
GUI_SaveContext(&ContextOld);
/* Make sure the next window to redraw is valid */
for (; iWin && UpdateRem;)
{
WM_Obj* pWin = WM_H2P(iWin);
if (_Paint(iWin, pWin))
{
UpdateRem--; /* Only the given number of windows at a time ... */
}
iWin = pWin->hNextLin;
}
NextDrawWin = iWin; /* Remember the window */
GUI_RestoreContext(&ContextOld);
}
/*********************************************************************
*
* WM_Exec1
*/
int WM_Exec1(void)
{
/* Poll PID if necessary */
if (WM_pfPollPID)
{
WM_pfPollPID();
}
if (WM_pfHandlePID)
{
if (WM_pfHandlePID())
{
return 1;
} /* We have done something ... */
}
if (GUI_PollKeyMsg())
{
return 1; /* We have done something ... */
}
if (WM_IsActive && WM__NumInvalidWindows)
{
WM_LOCK();
_DrawNext();
WM_UNLOCK();
return 1; /* We have done something ... */
}
return 0; /* There was nothing to do ... */
}
/*********************************************************************
*
* WM_Exec
*/
int WM_Exec(void)
{
int r = 0;
while (WM_Exec1())
{
r = 1; /* We have done something */
}
return r;
}
/*********************************************************************
*
* cbBackWin
*
* Purpose
* Callback for background window
*
*/
static void cbBackWin(WM_MESSAGE *pMsg)
{
const WM_KEY_INFO* pKeyInfo;
switch (pMsg->MsgId)
{
case WM_KEY:
pKeyInfo = (const WM_KEY_INFO *) pMsg->Data.p;
if (pKeyInfo->PressedCnt == 1)
{
GUI_StoreKey(pKeyInfo->Key);
}
break;
case WM_PAINT:
{
int LayerIndex;
#if GUI_NUM_LAYERS > 1
LayerIndex = _DesktopHandle2Index(pMsg->hWin);
#else
LayerIndex = 0;
#endif
if (WM__aBkColor[LayerIndex] != GUI_INVALID_COLOR)
{
GUI_SetBkColor(WM__aBkColor[LayerIndex]);
GUI_Clear();
}
}
default:
WM_DefaultProc(pMsg);
}
}
/*********************************************************************
*
* WM_Activate
*/
void WM_Activate(void)
{
WM_IsActive = 1; /* Running */
}
/*********************************************************************
*
* WM_Deactivate
*/
void WM_Deactivate(void)
{
WM_IsActive = 0; /* No clipping performed by WM */
WM_LOCK();
LCD_SetClipRectMax();
WM_UNLOCK();
}
/*********************************************************************
*
* WM_DefaultProc
*
* Purpose
* Default callback for windows
* Any window should call this routine in the "default" part of the
* its callback function for messages it does not handle itself.
*
*/
void WM_DefaultProc(WM_MESSAGE *pMsg)
{
WM_HWIN hWin = pMsg->hWin;
const void *p = pMsg->Data.p;
WM_Obj* pWin = WM_H2P(hWin);
/* Exec message */
switch (pMsg->MsgId)
{
case WM_GET_INSIDE_RECT:
/* return client window in absolute (screen) coordinates */
WM__GetClientRectWin(pWin, (GUI_RECT *) p);
break;
case WM_GET_CLIENT_WINDOW:
/* return handle to client window. For most windows, there is no seperate client window, so it is the same handle */
pMsg->Data.v = (int) hWin;
return; /* Message handled */
case WM_KEY:
WM_SendToParent(hWin, pMsg);
return; /* Message handled */
case WM_GET_BKCOLOR:
pMsg->Data.Color = GUI_INVALID_COLOR;
return; /* Message handled */
case WM_NOTIFY_ENABLE:
WM_InvalidateWindow(hWin);
return; /* Message handled */
}
/* Message not handled. If it queries something, we return 0 to be on the safe side. */
pMsg->Data.v = 0;
pMsg->Data.p = 0;
}
/*********************************************************************
*
* WM_Init
*/
void WM_Init(void)
{
if (!_IsInited)
{
NextDrawWin = WM__FirstWin = WM_HWIN_NULL;
GUI_Context.WM__pUserClipRect = NULL;
WM__NumWindows = WM__NumInvalidWindows = 0;
/* Make sure we have at least one window. This greatly simplifies the
drawing routines as they do not have to check if the window is valid.
*/
#if GUI_NUM_LAYERS == 1
WM__ahDesktopWin[0] = WM_CreateWindow(0, 0, GUI_XMAX, GUI_YMAX, WM_CF_SHOW, cbBackWin, 0);
WM__aBkColor[0] = GUI_INVALID_COLOR;
WM_InvalidateWindow(WM__ahDesktopWin[0]); /* Required because a desktop window has no parent. */
#else
{
int i;
for (i = 0; i < GUI_NUM_LAYERS; i++)
{
WM__ahDesktopWin[i] = WM_CreateWindowAsChild(0, 0, GUI_XMAX, GUI_YMAX, WM_UNATTACHED, WM_CF_SHOW, cbBackWin, 0);
WM__aBkColor[i] = GUI_INVALID_COLOR;
WM_InvalidateWindow(WM__ahDesktopWin[i]); /* Required because a desktop window has no parent. */
}
}
#endif
/* Register the critical handles ... Note: This could be moved into the module setting the Window handle */
WM__AddCriticalHandle(&WM__CHWinModal);
WM__AddCriticalHandle(&WM__CHWinLast);
WM_SelectWindow(WM__ahDesktopWin[0]);
WM_Activate();
_IsInited = 1;
}
}
#else
void WM(void)
{
} /* avoid empty object files */
#endif /* GUI_WINSUPPORT */
/*************************** End of file ****************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -