📄 wm.c
字号:
WM__NumWindows++;
pWin = WM_H2P(hWin);
memset (pWin, 0, sizeof(WM_Obj)); /* erase this data structure
The explicit zero-init is no longer needed since the entire data structure
is already zeroed. The advantage is that it reduces program size.
*/
pWin->Rect.x0 = x0;
pWin->Rect.y0 = y0;
pWin->Rect.x1 = x0+width-1;
pWin->Rect.y1 = y0+height-1;
pWin->Status = WM_SF_INUSE; /* Mark window as in use */
pWin->cb = cb;
/* Add to linked lists */
pWin->hParent = hParent;
_AddChild(hParent, hWin, Style & WM_CF_STAYONTOP);
_AddToLinList(hWin);
/* Put Window on top (or bottom) of windows stack */
if (Style & WM_CF_ACTIVATE /*| (cb==NULL)*/) {
WM_SelectWindow(hWin); /* This is not needed
if callbacks are being used, but it
does not cost a lot and makes life
easier ... */
}
/* Mark client area as invalid */
WM__SendMsgNoData(hWin, WM_CREATE);
/* Handle the Style flags, one at a time */
if (Style & WM_CF_SHOW) {
WM_ShowWindow(hWin);
}
/* Hide if parent is not visible */
if (hParent) {
WM_Obj* pWinParent = WM_H2P(hParent);
if (!(pWinParent->Status & WM_SF_ISVIS)) {
WM_HideWindow(hWin);
}
}
/* Copy the flags which can simply be accepted */
pWin->Status |= (Style & (WM_SF_MEMDEV|WM_SF_STAYONTOP|WM_SF_HASTRANS));
}
WM_UNLOCK();
return hWin;
}
WM_HWIN WM_CreateWindow(int x0, int y0, int width, int height, U16 Style, WM_CALLBACK* cb, int NumExtraBytes) {
return WM_CreateWindowAsChild(x0,y0,width,height, 0 /* No parent */, Style, cb, NumExtraBytes);
}
/****************************************************************
*
* Delete window
*
*****************************************************************
*/
void WM_DeleteWindow (WM_HWIN Win) {
WM_Obj* pWin;
if (!Win)
return;
WM_LOCK();
if (WM__IsWindow(Win)) {
pWin = WM_H2P(Win);
ResetNextDrawWin(); /* Make sure the window will no longer receive drawing messages */
/* Make sure that focus is set to an existing window */
if (WM__hWinFocus == Win) {
WM__hWinFocus = 0;
}
if (Win == WM__hCapture) {
WM__hCapture = 0;
}
/* Delete all children */
_DeleteAllChildren(pWin->hFirstChild);
_DeleteInSiblingList(Win);
/* Send WM_DELETE message to window in order to inform window itself */
WM__SendMsgNoData(Win, WM_DELETE); /* tell window about it */
/* Inform other modules if necessary */
if (WM__pfDeleteWindowHook) {
(*WM__pfDeleteWindowHook)(Win);
}
/* Remove window from window stack */
if (pWin->Status & WM_SF_INVALID) {
WM__NumInvalidWindows--;
}
WM__RemoveFromLinList(Win);
/* Clear area used by this window */
WM_InvalidateArea(&pWin->Rect);
/* Free window memory */
WM__NumWindows--;
WM_FREE(Win);
/* Select a valid window */
WM_SelectWindow(WM__FirstWin);
} else {
GUI_DEBUG_WARN("WM_DeleteWindow: Invalid handle");
}
WM_UNLOCK();
}
void WM__SetMaxClipRect(const WM_Obj* pWin) {
WM_LOCK();
LCD_SetClipRectEx(&pWin->Rect);
WM_UNLOCK();
}
/****************************************************************
*
* WM_SelectWindow
*
*****************************************************************
Sets the active Window. The active Window is the one that is used for all
drawing (and text) operations.
*/
WM_HWIN WM_SelectWindow(WM_HWIN hWin) {
WM_HWIN hWinPrev;
WM_LOCK();
hWinPrev = GUI_Context.hAWin;
if (hWin == 0) {
hWin = WM__FirstWin;
}
if (!(WM_H2P(hWin)->Status & WM_SF_INUSE)) {
GUI_DEBUG_ERROROUT1("Selecting invalid window", hWin);
hWin=0;
}
/* Select new window */
GUI_Context.hAWin = hWin;
WM__SetMaxClipRect(WM_H2P(hWin));
WM_UNLOCK();
return hWinPrev;
}
WM_HWIN WM_GetActiveWindow(void) {
return GUI_Context.hAWin;
}
/*
********************************************************************
* *
* Show / hide window *
* *
********************************************************************
*/
void WM_ShowWindow (WM_HWIN hWin) {
WM_Obj *pWin;
WM_LOCK();
pWin = WM_H2P(hWin);
/* First check if this is necessary at all */
if ((pWin->Status&WM_SF_ISVIS)) {
WM_UNLOCK();
return;
}
/* Set Visibility flag */
pWin->Status |= WM_SF_ISVIS;
/* Mark content as invalid */
WM_InvalidateWindow(hWin);
WM_UNLOCK();
}
/*
*****************************************************************
* *
* GetOrg *
* *
*****************************************************************
These routines return the offset of the client area in absolute coordinates.
They are used to convert window coordinates into absolute coordinates and are
used in the clipping libraries (CL_).
*/
int WM__GetOrgX(void) {
return WM_H2P(GUI_Context.hAWin)->Rect.x0;
}
int WM__GetOrgY(void) {
return WM_H2P(GUI_Context.hAWin)->Rect.y0;
}
/*********************************************************************
*
* IVR calculation
IVRs are invalid rectangles. When redrawing, only the portion of the
window which is
a) within the window-rectangle
b) not covered by an other window
c) marked as invalid
is actually redrawn. Unfortunately, this section is not always
rectangular. If the window is partially covered by an other window,
it consists of the sum of multiple rectangles. In all drawing
operations, we have to iterate over every one of these rectangles in
order to make sure the window is drawn completly.
Function works as follows:
STEP 1: - Set upper left coordinates to next pixel. If end of line (right border), goto next line -> (r.x0, r.y0)
STEP 2: - Check if we are done, return if we are.
STEP 3: - If we are at the left border, find max. heigtht (r.y1) by iterating over windows above
STEP 4: - Find x0 for the given y0, y1 by iterating over windows above
STEP 5: - If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
STEP 6: - Find r.x1. We have to Iterate over all windows which are above
*/
#if WM_SUPPORT_OBSTRUCT
static int FindNext_IVR(void) {
int hParent;
int iWin;
GUI_RECT r;
U8 Status;
WM_Obj* pWin;
WM_Obj* pAWin;
WM_Obj* pParent;
r = ClipContext.CurRect; /* temps so we do not have to work with pointers too much */
/*
STEP 1:
Set the next position which could be part of the next IVR
This will be the first unhandle pixel in reading order, i.e. next one to the right
or next one down if we are at the right border.
*/
if (ClipContext.Cnt == 0) { /* First IVR starts in upper left */
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -