📄 desktop.c
字号:
pTemp = (PMAINWIN)(pNode->hWnd);
if (pTemp->dwStyle & WS_VISIBLE)
SubtractClipRect (&pGCRInfo->crgn, (PRECT)(&pTemp->left));
pNode = pNode->pNext;
}
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
// where is the showing window?
pNode = TopMostWinZOrder.pTopMost;
while (pNode)
{
if (pNode->hWnd == (HWND)pWin)
break;
pNode = pNode->pNext;
}
// the showing main window's rect
memcpy (&rcWin, &pWin->left, sizeof(RECT));
// update all top most windows which covered by this showing window.
pNode = pNode->pNext;
while (pNode)
{
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
pthread_mutex_lock (&pGCRInfo->lock);
SubtractClipRect (&pGCRInfo->crgn, &rcWin);
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
}
pNode = pNode->pNext;
}
// update all normal main windows' global clip region
pNode = MainWinZOrder.pTopMost;
while (pNode)
{
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
pthread_mutex_lock (&pGCRInfo->lock);
SubtractClipRect (&pGCRInfo->crgn, &rcWin);
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
}
pNode = pNode->pNext;
}
// update desktop's global clip region.
pthread_mutex_lock (&sg_ScrGCRInfo.lock);
SubtractClipRect (&sg_ScrGCRInfo.crgn, &rcWin);
sg_ScrGCRInfo.age ++;
pthread_mutex_unlock (&sg_ScrGCRInfo.lock);
}
static BOOL dskDoesCoverOther (PMAINWIN pWin1, PMAINWIN pWin2)
{
PZORDERNODE pNode;
if (pWin1 == NULL) return FALSE;
if (pWin2 == NULL) return TRUE;
pNode = MainWinZOrder.pTopMost;
while(pNode)
{
if (pNode->hWnd == (HWND)pWin1) return TRUE;
if (pNode->hWnd == (HWND)pWin2) return FALSE;
pNode = pNode->pNext;
}
return FALSE;
}
static BOOL dskIsTopMost (PMAINWIN pWin)
{
if (pWin->dwExStyle & WS_EX_TOPMOST)
return ((HWND)pWin == TopMostWinZOrder.pTopMost->hWnd);
else
return ((HWND)pWin == MainWinZOrder.pTopMost->hWnd);
}
static PMAINWIN dskChangActiveWindow (PMAINWIN pWin)
{
PMAINWIN pOldActive;
if (sg_hIMEWnd && (sg_hIMEWnd == (HWND)pWin)) return pActiveMainWnd;
if (pWin == pActiveMainWnd) return pActiveMainWnd;
pOldActive = pActiveMainWnd;
DesktopSetActiveWindow (pWin);
if (pWin) {
SendAsyncMessage ((HWND)pWin, MSG_NCACTIVATE, TRUE, 0);
SendNotifyMessage ((HWND)pWin, MSG_ACTIVE, TRUE, 0);
SendNotifyMessage ((HWND)pWin, MSG_SETFOCUS, 0, 0);
}
if (pOldActive && (pOldActive->dwStyle & WS_VISIBLE)) {
SendAsyncMessage ((HWND)pOldActive, MSG_NCACTIVATE, FALSE, 0);
SendNotifyMessage ((HWND)pWin, MSG_ACTIVE, FALSE, 0);
SendNotifyMessage ((HWND)pOldActive, MSG_KILLFOCUS, 0, 0);
}
return pOldActive;
}
// This function called when a window was shown.
// return: the new active window.
// when return value is NULL, the active window not changed.
//
static PMAINWIN dskShowMainWindow(PMAINWIN pWin)
{
if (pWin->dwStyle & WS_VISIBLE)
return NULL;
if (pWin->dwExStyle & WS_EX_TOPMOST)
dskUpdateGCRInfoOnShowMainWinEx (pWin);
else
dskUpdateGCRInfoOnShowMainWin (pWin);
pWin->dwStyle |= WS_VISIBLE;
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
InvalidateRect ((HWND)pWin, NULL, TRUE);
if (pWin->dwExStyle & WS_EX_TOPMOST)
return dskChangActiveWindow (pWin);
// if the showing window cover the current active window
// set this window as the active one.
if (dskDoesCoverOther (pWin, pActiveMainWnd))
return dskChangActiveWindow (pWin);
return NULL;
}
// Main window hosting.
//
// Add new hosted main window.
//
void dskAddNewHostedMainWindow (PMAINWIN pHosting, PMAINWIN pHosted)
{
PMAINWIN head, prev;
pHosted->pNextHosted = NULL;
head = pHosting->pFirstHosted;
if (head)
{
while (head) {
prev = head;
head = head->pNextHosted;
}
prev->pNextHosted = pHosted;
}
else
pHosting->pFirstHosted = pHosted;
return;
}
// Main Window hosting.
//
// Remove a hosted main window.
//
void dskRemoveHostedMainWindow (PMAINWIN pHosting, PMAINWIN pHosted)
{
PMAINWIN head, prev;
head = pHosting->pFirstHosted;
if (head == pHosted)
{
pHosting->pFirstHosted = head->pNextHosted;
return;
}
while (head) {
prev = head;
head = head->pNextHosted;
if (head == pHosted) {
prev->pNextHosted = head->pNextHosted;
return;
}
}
return;
}
// this funciton add the new main window to the main window list.
// if new main window is a visible window,
// this new main window becomes the active window and this function
// return the old main window.
// otherwise, return NULL.
static PMAINWIN dskAddNewMainWindow(PMAINWIN pWin, PZORDERNODE pNode)
{
RECT rcTemp;
// Handle main window hosting.
if (pWin->pHosting)
dskAddNewHostedMainWindow (pWin->pHosting, pWin);
// Init Global Clip Region info.
pthread_mutex_init (&pWin->GCRInfo.lock, NULL);
pWin->GCRInfo.age = 0;
InitClipRgn (&pWin->GCRInfo.crgn, &sg_FreeClipRectList);
IntersectRect (&rcTemp, (PRECT)(&pWin->left), &sg_rcScr);
SetClipRgn (&pWin->GCRInfo.crgn, &rcTemp);
// Init Invalid Region info.
pthread_mutex_init (&pWin->InvRgn.lock, NULL);
InitClipRgn (&pWin->InvRgn.rgn, &sg_FreeInvRectList);
EmptyClipRgn (&pWin->InvRgn.rgn);
// Update Z Order info.
pNode->hWnd = (HWND)pWin;
if (pWin->dwExStyle & WS_EX_TOPMOST) {
pNode->pNext = TopMostWinZOrder.pTopMost;
TopMostWinZOrder.pTopMost = pNode;
TopMostWinZOrder.nNumber++;
}
else {
pNode->pNext = MainWinZOrder.pTopMost;
MainWinZOrder.pTopMost = pNode;
MainWinZOrder.nNumber++;
}
// show and active this main window.
if ( pWin->dwStyle & WS_VISIBLE ) {
if (pWin->dwExStyle & WS_EX_TOPMOST)
dskUpdateGCRInfoOnShowNewMainWinEx (pWin);
else
dskUpdateGCRInfoOnShowNewMainWin (pWin);
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
SendNotifyMessage ((HWND)pWin, MSG_SHOWWINDOW, SW_SHOWNORMAL, 0);
InvalidateRect ((HWND)pWin, NULL, TRUE);
return dskChangActiveWindow (pWin);
}
return NULL;
}
BOOL wndInvalidateRect (HWND hWnd, const RECT* prc, BOOL bEraseBkgnd);
// this function called when a visible main win becomes as a top most window.
// this is a normal main window.
static void dskUpdateGCRInfoOnChangeTopMost(PMAINWIN pNew)
{
PGCRINFO pGCRInfo;
PZORDERNODE pNode;
RECT rcInter;
RECT rcNew;
RECT rcOther;
BOOL inved = FALSE;
memcpy (&rcNew, &pNew->left, sizeof(RECT));
// clip all main windows which will covered by this new top most window
pNode = MainWinZOrder.pTopMost;
while (pNode)
{
if ( pNode->hWnd == (HWND)pNew )
break;
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
memcpy(&rcOther, &(((PMAINWIN)(pNode->hWnd))->left), sizeof(RECT));
if(IntersectRect(&rcInter, &rcNew, &rcOther))
{
pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
pthread_mutex_lock (&pGCRInfo->lock);
SubtractClipRect (&pGCRInfo->crgn, &rcNew);
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
// update this window's client area.
rcInter.left -= pNew->cl;
rcInter.top -= pNew->ct;
rcInter.right -= pNew->cl;
rcInter.bottom -= pNew->ct;
wndInvalidateRect ((HWND)pNew, &rcInter, TRUE);
inved = TRUE;
}
}
pNode = pNode->pNext;
}
if (inved)
PostMessage ((HWND)pNew, MSG_PAINT, 0, 0);
}
// this is a top most window
static void dskUpdateGCRInfoOnChangeTopMostEx (PMAINWIN pNew)
{
PGCRINFO pGCRInfo;
PZORDERNODE pNode;
RECT rcInter;
RECT rcNew;
RECT rcOther;
BOOL inved = FALSE;
memcpy (&rcNew, &pNew->left, sizeof(RECT));
pNode = TopMostWinZOrder.pTopMost;
while (pNode)
{
if ( pNode->hWnd == (HWND)pNew )
break;
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
memcpy(&rcOther, &(((PMAINWIN)(pNode->hWnd))->left), sizeof(RECT));
if(IntersectRect(&rcInter, &rcNew, &rcOther))
{
pGCRInfo = &((PMAINWIN)(pNode->hWnd))->GCRInfo;
pthread_mutex_lock (&pGCRInfo->lock);
SubtractClipRect (&pGCRInfo->crgn, &rcNew);
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
// update this window's client area.
rcInter.left -= pNew->cl;
rcInter.top -= pNew->ct;
rcInter.right -= pNew->cl;
rcInter.bottom -= pNew->ct;
wndInvalidateRect ((HWND)pNew, &rcInter, TRUE);
inved = TRUE;
}
}
pNode = pNode->pNext;
}
if (inved)
PostMessage ((HWND)pNew, MSG_PAINT, 0, 0);
}
// this function called when a main window becomes a visible top most window.
// Functions which lead to call this function:
// ShowWindow: show a invisible window with SW_SHOWNORMAL parameters.
//
// return: old active window.
//
static PMAINWIN dskMoveToTopMost(PMAINWIN pWin)
{
PZORDERNODE pNode, pTemp;
PMAINWIN pTempWin;
RECT rcTemp;
if (!pWin) return pActiveMainWnd;
if (dskIsTopMost (pWin) && (pWin->dwStyle & WS_VISIBLE))
return pActiveMainWnd;
// update this main window's global clip region info.
pthread_mutex_lock (&pWin->GCRInfo.lock);
IntersectRect (&rcTemp, (PRECT)(&pWin->left), &sg_rcScr);
SetClipRgn (&pWin->GCRInfo.crgn, &rcTemp);
if (!(pWin->dwExStyle & WS_EX_TOPMOST)) {
// clip by all top most windows
pNode = TopMostWinZOrder.pTopMost;
while (pNode)
{
pTempWin = (PMAINWIN)(pNode->hWnd);
if (pTempWin->dwStyle & WS_VISIBLE)
SubtractClipRect (&pWin->GCRInfo.crgn,
(PRECT)(&pTempWin->left));
pNode = pNode->pNext;
}
}
pWin->GCRInfo.age ++;
pthread_mutex_unlock (&pWin->GCRInfo.lock);
// activate this main window.
if ( !(pWin->dwStyle & WS_VISIBLE) )
{
// Update Z Order first.
if (pWin->dwExStyle & WS_EX_TOPMOST) {
pNode = TopMostWinZOrder.pTopMost;
if (pNode->hWnd != (HWND)pWin) {
while(pNode->pNext)
{
if( pNode->pNext->hWnd == (HWND)pWin )
{
pTemp = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
pTemp->pNext = TopMostWinZOrder.pTopMost;
TopMostWinZOrder.pTopMost = pTemp;
break;
}
pNode = pNode->pNext;
}
}
}
else {
pNode = MainWinZOrder.pTopMost;
if (pNode->hWnd != (HWND)pWin) {
while(pNode->pNext)
{
if( pNode->pNext->hWnd == (HWND)pWin )
{
pTemp = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
pTemp->pNext = MainWinZOrder.pTopMost;
MainWinZOrder.pTopMost = pTemp;
break;
}
pNode = pNode->pNext;
}
}
}
if (pWin->dwExStyle & WS_EX_TOPMOST)
dskUpdateGCRInfoOnShowNewMainWinEx (pWin);
else
dskUpdateGCRInfoOnShowNewMainWin (pWin);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -