📄 wm.c
字号:
r.x0 = ClipContext.ClientRect.x0;
r.y0 = ClipContext.ClientRect.y0;
} else {
r.x0 = ClipContext.CurRect.x1+1;
r.y0 = ClipContext.CurRect.y0;
if (r.x0 > ClipContext.ClientRect.x1) {
NextStripe: // go down to next stripe
r.x0 = ClipContext.ClientRect.x0;
r.y0 = ClipContext.CurRect.y1+1;
}
}
//
// STEP 2:
// Check if we are done completely.
if (r.y0 >ClipContext.ClientRect.y1)
return 0;
// STEP 3:
// Find out the max. height (r.y1) if we are at the left border.
// Since we are using the same height for all IVRs at the same y0,
// we do this only for the leftmost one.
pAWin = WM_H2P(GUI_Context.hAWin);
if (r.x0 == ClipContext.ClientRect.x0) {
r.y1 = ClipContext.ClientRect.y1;
r.x1 = ClipContext.ClientRect.x1;
// Iterate over all windows which are above
// Check all siblings above (Iterate over Parents and top siblings (hNext)
for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
// Check if this window affects us at all
if ((Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
if (pWin->Rect.y0 > r.y0) {
ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1); // Check upper border of window
} else {
ASSIGN_IF_LESS(r.y1, pWin->Rect.y1); // Check lower border of window
}
}
}
}
// Check all children
for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
// Check if this window affects us at all
if ((Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
if (pWin->Rect.y0 > r.y0) {
ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1); // Check upper border of window
} else {
ASSIGN_IF_LESS(r.y1, pWin->Rect.y1); // Check lower border of window
}
}
}
}
//
// STEP 4
// Find out x0 for the given y0, y1 by iterating over windows above.
// if we find one that intersects, adjust x0 to the right.
//
Find_x0:
r.x1 = r.x0;
// Iterate over all windows which are above
// Check all siblings above
for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) { // Check if this window affects us at all
r.x0 = pWin->Rect.x1+1;
goto Find_x0;
}
}
}
// Check all children
for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) { // Check if this window affects us at all
r.x0 = pWin->Rect.x1+1;
goto Find_x0;
}
}
//
// STEP 5:
// If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
// Find out x1 for the given x0, y0, y1
r.x1 = ClipContext.ClientRect.x1;
if (r.x1 < r.x0) {// horizontal border reached ?
ClipContext.CurRect = r;
goto NextStripe;
}
//
// STEP 6:
// Find r.x1. We have to Iterate over all windows which are above
// Check all siblings above (Iterate over Parents and top siblings (hNext)
for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) { // Check if this window affects us at all
r.x1 = pWin->Rect.x0-1;
}
}
}
// Check all children
for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
Status = (pWin = WM_H2P(iWin))->Status;
if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) { // Check if this window affects us at all
r.x1 = pWin->Rect.x0-1;
}
}
// We are done. Return the rectangle we found in the ClipContext.
if (ClipContext.Cnt >200) {
return 0; // error !!! This should not happen !
}
ClipContext.CurRect = r;
return 1; // IVR is valid !
}
#else
static int FindNext_IVR(void) {
if (ClipContext.Cnt ==0) {
ClipContext.CurRect = GUI_Context.pAWin->Rect;
return 1; // IVR is valid !
}
return 0; // Nothing left to draw
}
#endif
/********************************************************************
*
* Get next IVR
Sets the next clipping rectangle. If a valid one has
been found (and set), 1 is returned in order to indicate
that the drawing operation needs to be executed.
Returning 0 signals that we have iterated over all
rectangles.
Returns: 0 if no valid rectangle is found
1 if rectangle has been found
*/
int WM__GetNextIVR (void) {
#if GUI_SUPPORT_CURSOR
static char _CursorHidden;
#endif
// If WM is not active, we have no rectangles to return
if (WM_IsActive==0)
return 0;
if (ClipContext.EntranceCnt > 1) {
ClipContext.EntranceCnt--;
return 0;
}
#if GUI_SUPPORT_CURSOR
if (_CursorHidden) {
_CursorHidden = 0;
(*GUI_CURSOR_pfTempUnhide) ( &ClipContext.CurRect);
}
#endif
++ClipContext.Cnt;
// Find next rectangle and use it as ClipRect
if (!FindNext_IVR()) {
ClipContext.EntranceCnt--; // This search is over !
return 0; // Could not find an other one !
}
// Hide cursor if necessary
LCD_SetClipRectEx(&ClipContext.CurRect);
#if GUI_SUPPORT_CURSOR
if (GUI_CURSOR_pfTempHide) {
_CursorHidden = 1;
(*GUI_CURSOR_pfTempHide) ( &ClipContext.CurRect);
}
#endif
return 1;
}
/********************************************************************
*
* Init IVR search
This routine is called from the clipping level
(the WM_ITERATE_START macro) when starting an iteration over the
visible rectangles.
Return value:
0 : There is no valid rectangle (nothing to do ...)
1 : There is a valid rectangle
*/
int WM__InitIVRSearch(const GUI_RECT* pMaxRect) {
GUI_RECT r;
WM_Obj* pAWin;
// If WM is not active -> nothing to do, leave cliprect alone
if (WM_IsActive==0)
return 1;
// If we entered multiple times, leave Cliprect alone
if (++ClipContext.EntranceCnt > 1)
return 1;
pAWin = WM_H2P(GUI_Context.hAWin);
ClipContext.Cnt = -1;
// When using callback mechanism, it is legal to reduce drawing
// area to the invalid area !
if (IsInCallback) {
WM__GetInvalidRectAbs(pAWin, &r);
} else { // Not using callback mechanism, therefor allow entire rectangle
if (pAWin->Status & WM_SF_ISVIS) {
r = pAWin->Rect;
} else {
--ClipContext.EntranceCnt;
return 0; // window is not even visible !
}
}
// If the drawing routine has specified a rectangle, use it to reduce the rectangle
if (pMaxRect) {
GUI__IntersectRect(&r, pMaxRect);
}
// If user has reduced the cliprect size, reduce the rectangle
if (GUI_Context.WM__pUserClipRect) {
GUI_RECT rUser = *(GUI_Context.WM__pUserClipRect);
WM__Client2Screen(pAWin, &rUser);
GUI__IntersectRect(&r, &rUser);
}
// Iterate over all ancestors and clip at their borders
_ClipAtParentBorders(&r, pAWin);
// Store the rectangle and find the first rectangle of the area
ClipContext.ClientRect = r;
return WM__GetNextIVR();
}
/*
********************************************
* *
* Set default *
* *
********************************************
This routine sets the defaults for WM and the layers below.
It is used before a drawing routine is called in order to
make sure that defaults are set (in case the default settings
had been altered before by the application)
*/
void WM_SetDefault(void) {
GL_SetDefault();
GUI_Context.WM__pUserClipRect = NULL; // No add. clipping
}
/*
********************************************
*
* 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.
*/
#if GUI_SUPPORT_MEMDEV
static void cbPaint(void* pMsg) {
WM_SendMessage(((WM_MESSAGE*)pMsg)->hWin, (WM_MESSAGE*) pMsg);
}
#endif
/*
********************************************
* *
* Draw next window *
* *
********************************************
*/
static void _DrawNext(void) {
int UpdateRem = 1;
WM_HWIN iWin = (NextDrawWin == WM_HWIN_NULL) ? WM__FirstWin : NextDrawWin;
GUI_CONTEXT ContextOld;
GUI_SaveContext(&ContextOld); //save old context
// Make sure the next window to redraw is valid
for (; (iWin!=WM_HWIN_NULL) && UpdateRem; ) {
WM_Obj* pWin = WM_H2P(iWin);
if (pWin->Status & WM_SF_INVALID) { //if status flag is invalue
U8 Status = (pWin->Status &= ~WM_SF_INVALID); // Clear invalid flag
WM__NumInvalidWindows--; //update the number of invalue windows
// Send WM_PAINT if window is visible and a callback is defined
if ((pWin->cb != NULL) && (Status & WM_SF_ISVIS)) {
WM_MESSAGE Msg;
Msg.hWin = iWin;
Msg.MsgId = WM_PAINT;
Msg.Data.p = (GUI_RECT*)&pWin->InvalidRect;
WM_SelectWindow(iWin); //select the new window
WM_SetDefault(); //set default config,e.g. font,pensize...
/*
#if GUI_SUPPORT_MEMDEV
if (Status & WM_SF_MEMDEV) {
GUI_RECT r = pWin->InvalidRect;
GUI_MoveRect (&r, pWin->Rect.x0, pWin->Rect.y0);
//GUI_MEMDEV_Draw(&r, cbPaint, &Msg, 0, (Status & WM_SF_HASTRANS) ? GUI_MEMDEV_HASTRANS : 0);
} else
#endif
*/
WM_SendMessage(iWin, &Msg);//send message "WM_PAINT" to current window.
UpdateRem--; // Only the given number of windows at a time ...
}
}
iWin = pWin->hNextLin;
}
NextDrawWin = iWin; // Remember the window
GUI_RestoreContext(&ContextOld);
}
/*
*****************************************************************
* *
* Idle loop *
* *
*****************************************************************
*/
int WM_Exec1(void) {
if (WM_pfHandleHID) {
if (WM_pfHandleHID())
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 ...
}
int WM_Exec(void) {
int r = 0;
while (WM_Exec1()) {
r = 1; // We have done something
}
return r;
}
/***************************************************************
* *
* Callback for background window *
* *
*****************************************************************
*/
static WM_RESULT cbBackWin(WM_MESSAGE* pMsg) {
WM_KEY_INFO* pKeyInfo;
switch (pMsg->MsgId) {
case WM_KEY:
pKeyInfo = (WM_KEY_INFO*)pMsg->Data.p;
if (pKeyInfo->PressedCnt == 0) {
GUI_StoreKey(pKeyInfo->Key);
}
break;
case WM_PAINT:
if (WM__BkColor != GUI_INVALID_COLOR) {
GUI_SetBkColor(WM__BkColor);
GUI_Clear();
}
default:
WM_DefaultProc(pMsg);
}
}
/***************************************************************
*
* WM_Activate / WM_Deactivate
*
*****************************************************************
*/
void WM_Activate(void) {
WM_IsActive = 1; // Running
}
void WM_Deactivate(void) {
WM_IsActive = 0; // No clipping performed by WM
WM__SetMaxClipRect(WM_H2P(WM_HBKWIN));
}
/*
*****************************************************************
* *
* WM_Init *
* *
*****************************************************************
*/
void WM_Init(void) {
if (!_IsInited) {
WM_HWIN hWin;
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.
hWin = WM_CreateWindow(LCD_ORGX, LCD_ORGY, GUI_XMAX, GUI_YMAX, WM_CF_SHOW, cbBackWin, 0);
//hWin = WM_CreateWindow(0, 0, 320, 240, WM_CF_SHOW, cbBackWin, 0);
WM_SelectWindow(hWin);
WM_Activate();
_IsInited =1;
}
}
/*
******************************************************
* *
* Default procedure *
* *
******************************************************
*/
WM_RESULT WM_DefaultProc(WM_MESSAGE* pMsg) {
WM_HWIN hWin = pMsg->hWin;
void *p = pMsg->Data.p;
WM_Obj* pWin = WM_H2P(hWin);
// Exec message
switch (pMsg->MsgId) {
case WM_GETORG:
((GUI_POINT*)p)->x = pWin->Rect.x0;
((GUI_POINT*)p)->y = pWin->Rect.y0;
break;
case WM_GETCLIENTRECT: // return client window in window coordinates
WM__GetClientRectWin(pWin, (GUI_RECT*)p);
break;
case WM_GETCLIENTRECT_ABS: // return client window in absolute (screen) coordinates
WM__GetClientRectWin(pWin, (GUI_RECT*)p);
GUI_MoveRect((GUI_RECT*)p, pWin->Rect.x0, pWin->Rect.y0);
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 = 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
}
// Message not handled. If it queries something, we return 0 to be on the safe side.
pMsg->Data.v = 0;
pMsg->Data.p = 0;
}
#else
void WM(void) {} // avoid empty object files
#endif // WM_MAX_WINDOW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -