📄 desktop-comm.c
字号:
{
PZORDERNODE pNode;
if (pWin1 == NULL) return FALSE;
if (pWin2 == NULL) return TRUE;
pNode = sg_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 == sg_TopMostWinZOrder.pTopMost->hWnd);
else
return ((HWND)pWin == sg_MainWinZOrder.pTopMost->hWnd);
}
static PMAINWIN dskChangActiveWindow (PMAINWIN pWin)
{
PMAINWIN pOldActive;
if (__mg_ime_wnd && (__mg_ime_wnd == (HWND)pWin))
return __mg_active_mainwnd;
if ((pWin == __mg_active_mainwnd)
|| (pWin && (pWin->dwExStyle & WS_EX_TOOLWINDOW)))
return __mg_active_mainwnd;
pOldActive = __mg_active_mainwnd;
DesktopSetActiveWindow (pWin);
if (pOldActive && (pOldActive->dwStyle & WS_VISIBLE)) {
SendAsyncMessage ((HWND)pOldActive, MSG_NCACTIVATE, FALSE, 0);
SendNotifyMessage ((HWND)pOldActive, MSG_ACTIVE, FALSE, 0);
SendNotifyMessage ((HWND)pOldActive, MSG_KILLFOCUS, (HWND)pWin, 0);
}
if (pWin) {
SendAsyncMessage ((HWND)pWin, MSG_NCACTIVATE, TRUE, 0);
SendNotifyMessage ((HWND)pWin, MSG_ACTIVE, TRUE, 0);
SendNotifyMessage ((HWND)pWin, MSG_SETFOCUS, (HWND)pOldActive, 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, BOOL bActive)
{
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 (bActive && dskDoesCoverOther (pWin, __mg_active_mainwnd))
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;
}
static void init_gcrinfo (PMAINWIN pWin)
{
RECT rcWin, rcTemp;
dskGetWindowRectInScreen (pWin, &rcWin);
#ifndef _LITE_VERSION
pthread_mutex_init (&pWin->pGCRInfo->lock, NULL);
#endif
pWin->pGCRInfo->age = 0;
InitClipRgn (&pWin->pGCRInfo->crgn, &sg_FreeClipRectList);
IntersectRect (&rcTemp, &rcWin, &g_rcDesktop);
SetClipRgn (&pWin->pGCRInfo->crgn, &rcTemp);
}
static void init_invrgn (PMAINWIN pWin)
{
#ifndef _LITE_VERSION
pthread_mutex_init (&pWin->InvRgn.lock, NULL);
#endif
pWin->InvRgn.frozen = 0;
InitClipRgn (&pWin->InvRgn.rgn, &sg_FreeInvRectList);
EmptyClipRgn (&pWin->InvRgn.rgn);
}
static void add_new_window (ZORDERINFO* zorder, PZORDERNODE pNode)
{
pNode->pNext = zorder->pTopMost;
zorder->pTopMost = pNode;
zorder->nNumber++;
}
static void remove_window (ZORDERINFO* zorder, PMAINWIN pWin)
{
PZORDERNODE pNode, pTemp;
pNode = zorder->pTopMost;
if (pNode->hWnd == (HWND)pWin) {
zorder->pTopMost = pNode->pNext;
}
else {
while (pNode->pNext) {
if (pNode->pNext->hWnd == (HWND)pWin) {
pTemp = pNode->pNext->pNext;
pNode->pNext = pTemp;
break;
}
pNode = pNode->pNext;
}
}
zorder->nNumber--;
}
// 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)
{
// Handle main window hosting.
if (pWin->pHosting)
dskAddNewHostedMainWindow (pWin->pHosting, pWin);
// Init Global Clip Region info.
init_gcrinfo (pWin);
// Init Invalid Region info.
init_invrgn (pWin);
// Update Z Order info.
pNode->hWnd = (HWND)pWin;
if (pWin->dwExStyle & WS_EX_TOPMOST)
add_new_window (&sg_TopMostWinZOrder, pNode);
else
add_new_window (&sg_MainWinZOrder, pNode);
// 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;
}
// This function defined in gui/window.c
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 BOOL update_on_change_topmost (ZORDERINFO* zorder, PMAINWIN pNew, RECT* rcNew)
{
PGCRINFO pGCRInfo;
PZORDERNODE pNode;
RECT rcInter;
RECT rcOther;
BOOL inved = FALSE;
// clip all main windows which will covered by this new top most window
pNode = zorder->pTopMost;
while (pNode)
{
if ( pNode->hWnd == (HWND)pNew )
break;
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
dskGetWindowRectInScreen ((PMAINWIN)pNode->hWnd, &rcOther);
if (IntersectRect(&rcInter, rcNew, &rcOther)) {
pGCRInfo = ((PMAINWIN)(pNode->hWnd))->pGCRInfo;
#ifndef _LITE_VERSION
pthread_mutex_lock (&pGCRInfo->lock);
#endif
SubtractClipRect (&pGCRInfo->crgn, rcNew);
pGCRInfo->age ++;
#ifndef _LITE_VERSION
pthread_mutex_unlock (&pGCRInfo->lock);
#endif
// update this window's client area.
dskScreenToClient (pNew, &rcInter, &rcInter);
wndInvalidateRect ((HWND)pNew, &rcInter, TRUE);
inved = TRUE;
}
}
pNode = pNode->pNext;
}
return inved;
}
static void dskUpdateGCRInfoOnChangeTopMost(PMAINWIN pNew)
{
RECT rcNew;
dskGetWindowRectInScreen (pNew, &rcNew);
if (update_on_change_topmost (&sg_MainWinZOrder, pNew, &rcNew));
PostMessage ((HWND)pNew, MSG_PAINT, 0, 0);
}
// this is a top most window
static void dskUpdateGCRInfoOnChangeTopMostEx (PMAINWIN pNew)
{
RECT rcNew;
dskGetWindowRectInScreen (pNew, &rcNew);
if (update_on_change_topmost (&sg_TopMostWinZOrder, pNew, &rcNew))
PostMessage ((HWND)pNew, MSG_PAINT, 0, 0);
}
static void move_to_top (ZORDERINFO* zorder, PMAINWIN pWin)
{
PZORDERNODE pNode, pTemp;
pNode = zorder->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 = zorder->pTopMost;
zorder->pTopMost = pTemp;
break;
}
pNode = pNode->pNext;
}
}
}
static PMAINWIN dskHideMainWindow (PMAINWIN pWin);
static void dskSetPrimitiveChildren (PMAINWIN pWin, BOOL bSet)
{
PMAINWIN pParent = (PMAINWIN) pWin->hParent;
if (bSet) {
while (pParent) {
pParent->hPrimitive = (HWND)pWin;
pWin = pParent;
pParent = (PMAINWIN) pWin->hParent;
}
}
else {
while (pParent) {
pParent->hPrimitive = 0;
pWin = pParent;
pParent = (PMAINWIN) pWin->hParent;
}
}
}
// 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, int reason, LPARAM lParam)
{
RECT rcWin;
PMAINWIN pOldTopMost;
if (!pWin) return __mg_active_mainwnd;
if (pWin->dwExStyle & WS_EX_TOPMOST)
pOldTopMost = (PMAINWIN) sg_TopMostWinZOrder.pTopMost->hWnd;
else
pOldTopMost = (PMAINWIN) sg_MainWinZOrder.pTopMost->hWnd;
if (pOldTopMost && (pOldTopMost->WinType == TYPE_CONTROL)
&& (pOldTopMost->dwStyle & WS_VISIBLE)) {
dskHideMainWindow (pOldTopMost);
dskSetPrimitiveChildren (pOldTopMost, FALSE);
SendNotifyMessage (pOldTopMost->hParent,
MSG_CHILDHIDDEN, reason, lParam);
}
if (dskIsTopMost (pWin) && (pWin->dwStyle & WS_VISIBLE))
return __mg_active_mainwnd;
// update this main window's global clip region info.
dskGetWindowRectInScreen (pWin, &rcWin);
start_clip_window (pWin);
reset_window (pWin, &rcWin);
if (!(pWin->dwExStyle & WS_EX_TOPMOST))
clip_by_windows (&sg_TopMostWinZOrder, pWin);
end_clip_window (pWin);
// activate this main window.
if ( !(pWin->dwStyle & WS_VISIBLE) ) {
// Update Z Order first.
if (pWin->dwExStyle & WS_EX_TOPMOST)
move_to_top (&sg_TopMostWinZOrder, pWin);
else
move_to_top (&sg_MainWinZOrder, pWin);
if (pWin->dwExStyle & WS_EX_TOPMOST)
dskUpdateGCRInfoOnShowNewMainWinEx (pWin);
else
dskUpdateGCRInfoOnShowNewMainWin (pWin);
pWin->dwStyle |= WS_VISIBLE;
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
InvalidateRect ((HWND)pWin, NULL, TRUE);
}
else {
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
if (pWin->dwExStyle & WS_EX_TOPMOST)
dskUpdateGCRInfoOnChangeTopMostEx (pWin);
else
dskUpdateGCRInfoOnChangeTopMost (pWin);
// then update Z Order.
if (pWin->dwExStyle & WS_EX_TOPMOST)
move_to_top (&sg_TopMostWinZOrder, pWin);
else
move_to_top (&sg_MainWinZOrder, pWin);
}
if (reason != RCTM_SHOWCTRL)
return dskChangActiveWindow (pWin);
else
return __mg_active_mainwnd;
}
static void recalc_windows_under_this (ZORDERINFO* zorder, PMAINWIN pWin, RECT* rcWin)
{
PZORDERNODE pNode, pAffected;
RECT rcTemp, rcInv;
PMAINWIN pTemp;
// where is the hidding main window?
pNode = zorder->pTopMost;
while (pNode->hWnd != (HWND)pWin)
pNode = pNode->pNext;
pAffected = pNode->pNext;
while (pAffected){
pTemp = (PMAINWIN)(pAffected->hWnd);
if (pTemp->dwStyle & WS_VISIBLE) {
start_clip_window (pTemp);
dskGetWindowRectInScreen (pTemp, &rcTemp);
reset_window (pTemp, &rcTemp);
if (zorder != &sg_TopMostWinZOrder) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -