mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-06 18:31:57 +08:00
2204 lines
61 KiB
C
2204 lines
61 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IMPORTANT NOTICE
|
|
//
|
|
// The following open source license statement does not apply to any
|
|
// entity in the Exception List published by FMSoft.
|
|
//
|
|
// For more information, please visit:
|
|
//
|
|
// https://www.fmsoft.cn/exception-list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
|
* and Graphics User Interface (GUI) support system for embedded systems
|
|
* and smart IoT devices.
|
|
*
|
|
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
|
|
* Copyright (C) 1998~2002, WEI Yongming
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Or,
|
|
*
|
|
* As this program is a library, any link to this program must follow
|
|
* GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
* GPLv3, you need to be licensed from FMSoft.
|
|
*
|
|
* If you have got a commercial license of this program, please use it
|
|
* under the terms and conditions of the commercial license.
|
|
*
|
|
* For more information about the commercial license, please refer to
|
|
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
|
|
*/
|
|
/*
|
|
** desktop-comm.c: The Desktop module.
|
|
**
|
|
** Current maintainer: Wei Yongming.
|
|
**
|
|
*/
|
|
|
|
/* only for MiniGUI-Threads or MiniGUI-Standalone */
|
|
#include "desktop.c"
|
|
|
|
#if defined(_MGRM_THREADS) || defined(_MGRM_STANDALONE)
|
|
|
|
static LRESULT DesktopWinProc (HWND hWnd, UINT msg,
|
|
WPARAM wParam, LPARAM lParam);
|
|
|
|
static void init_desktop_win (void)
|
|
{
|
|
static MAINWIN sg_desktop_win;
|
|
PMAINWIN pDesktopWin;
|
|
|
|
LICENSE_SET_MESSAGE_OFFSET();
|
|
|
|
pDesktopWin = &sg_desktop_win;
|
|
|
|
pDesktopWin->pMsgQueue = __mg_dsk_msg_queue;
|
|
pDesktopWin->MainWindowProc = DesktopWinProc;
|
|
|
|
pDesktopWin->DataType = TYPE_HWND;
|
|
pDesktopWin->WinType = TYPE_ROOTWIN;
|
|
|
|
pDesktopWin->pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF);
|
|
pDesktopWin->spCaption = "THE DESKTOP WINDOW";
|
|
|
|
pDesktopWin->pGCRInfo = &sg_ScrGCRInfo;
|
|
pDesktopWin->idx_znode = 0;
|
|
|
|
pDesktopWin->pMainWin = pDesktopWin;
|
|
pDesktopWin->we_rdr = __mg_def_renderer;
|
|
|
|
__mg_hwnd_desktop = (HWND)pDesktopWin;
|
|
__mg_dsk_win = pDesktopWin;
|
|
|
|
__mg_dsk_msg_queue->pRootMainWin = __mg_dsk_win;
|
|
}
|
|
|
|
static PMAINWIN dskGetActiveWindow (void)
|
|
{
|
|
ZORDERNODE* nodes;
|
|
|
|
nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
return (PMAINWIN)nodes[__mg_zorder_info->active_win].hwnd;
|
|
}
|
|
|
|
static PMAINWIN dskSetActiveWindow (PMAINWIN pWin)
|
|
{
|
|
PMAINWIN pOldActive = dskGetActiveWindow();
|
|
|
|
if (pWin == pOldActive)
|
|
return pOldActive;
|
|
|
|
pOldActive = (PMAINWIN) dskSetActiveZOrderNode (__mg_zorder_info, 0, pWin?pWin->idx_znode:0);
|
|
|
|
#ifndef _MGRM_PROCESSES /*for MiniGUI-Threads, not for MiniGUI-StandAlone*/
|
|
if (pOldActive != (PMAINWIN)HWND_INVALID && __mg_ime_wnd)
|
|
SendNotifyMessage (__mg_ime_wnd, MSG_IME_SETTARGET, (WPARAM)pWin, 0);
|
|
#endif
|
|
|
|
return pOldActive;
|
|
}
|
|
|
|
/*
|
|
* Shows/Activates a main window.
|
|
* This function called when a window was shown.
|
|
*/
|
|
static void dskShowMainWindow (PMAINWIN pWin, BOOL bActive)
|
|
{
|
|
if (pWin->dwStyle & WS_VISIBLE)
|
|
return;
|
|
|
|
//dskUpdateGCRInfoOnShowMainWin (pWin);
|
|
|
|
pWin->dwStyle |= WS_VISIBLE;
|
|
dskShowWindow (0, pWin->idx_znode);
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect ((HWND)pWin, NULL, TRUE);
|
|
|
|
#if 0
|
|
if (pWin->dwExStyle & WS_EX_TOPMOST)
|
|
return dskSetActiveWindow (pWin);
|
|
|
|
// if the showing window cover the current active window
|
|
// set this window as the active one.
|
|
//if (bActive && dskDoesCoverOther (pWin, dskGetActiveWindow()))
|
|
#endif
|
|
if (bActive)
|
|
dskSetActiveWindow (pWin);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
static int dskAllocZOrderNode (PMAINWIN pWin)
|
|
{
|
|
RECT rc;
|
|
|
|
dskGetWindowRectInScreen (pWin, &rc);
|
|
|
|
return AllocZOrderNode (0, (HWND)pWin,
|
|
(HWND)pWin->pMainWin,
|
|
get_znode_flags_from_style (pWin),
|
|
&rc, pWin->spCaption, HDC_INVALID,
|
|
CT_OPAQUE, 0);
|
|
}
|
|
|
|
/*
|
|
* This funciton add the new main window to the z-order list.
|
|
* If new main window is a visible window,
|
|
* this new main window becomes the active window.
|
|
*
|
|
* Return 0 if OK, else -1;
|
|
*/
|
|
static int dskAddNewMainWindow (PMAINWIN pWin)
|
|
{
|
|
pWin->pGCRInfo = &pWin->GCRInfo;
|
|
|
|
// Update Z Order info.
|
|
pWin->idx_znode = dskAllocZOrderNode (pWin);
|
|
|
|
if (pWin->idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
/* Since 5.0.0: handle window style if failed to allocate znode
|
|
for special main window */
|
|
if (pWin->dwExStyle & WS_EX_WINTYPE_MASK) {
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
pWin->dwExStyle &= ~WS_EX_WINTYPE_MASK;
|
|
switch (nodes [pWin->idx_znode].flags & ZOF_TYPE_MASK) {
|
|
case ZOF_TYPE_TOOLTIP:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_TOOLTIP;
|
|
break;
|
|
case ZOF_TYPE_GLOBAL:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_GLOBAL;
|
|
break;
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_SCREENLOCK;
|
|
break;
|
|
case ZOF_TYPE_DOCKER:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_DOCKER;
|
|
break;
|
|
case ZOF_TYPE_HIGHER:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_HIGHER;
|
|
pWin->dwExStyle |= WS_EX_TOPMOST;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_NORMAL;
|
|
break;
|
|
case ZOF_TYPE_LAUNCHER:
|
|
pWin->dwExStyle |= WS_EX_WINTYPE_LAUNCHER;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if 0 /* move to window.c since 5.0.0 */
|
|
// Handle main window hosting.
|
|
if (pWin->pHosting)
|
|
dskAddNewHostedMainWindow (pWin->pHosting, pWin);
|
|
#endif /* moved code */
|
|
|
|
// Init Global Clip Region info.
|
|
dskInitGCRInfo (pWin);
|
|
|
|
// Init Invalid Region info.
|
|
dskInitInvRgn (pWin);
|
|
|
|
/* houhh 20081128, create secondary window dc before
|
|
* InvalidateRect, erase_bk will used this. */
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC) {
|
|
pWin->secondaryDC = CreateSecondaryDC ((HWND)pWin);
|
|
pWin->update_secdc = ON_UPDSECDC_DEFAULT;
|
|
}
|
|
|
|
if (pWin->secondaryDC == HDC_INVALID) {
|
|
/* remove the flag of WS_EX_AUTOSECONDARYDC */
|
|
pWin->dwExStyle &= ~WS_EX_AUTOSECONDARYDC;
|
|
pWin->secondaryDC = 0;
|
|
|
|
}
|
|
|
|
/* Create private client dc. */
|
|
if (pWin->dwExStyle & WS_EX_USEPRIVATECDC) {
|
|
#if 0 /* deprecated code */
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC)
|
|
pWin->privCDC = GetSecondarySubDC (pWin->secondaryDC,
|
|
(HWND)pWin, TRUE);
|
|
else
|
|
pWin->privCDC = CreatePrivateClientDC ((HWND)pWin);
|
|
#else
|
|
/* since 5.0.0, always call CreatePrivateClientDC */
|
|
pWin->privCDC = CreatePrivateClientDC ((HWND)pWin);
|
|
#endif
|
|
}
|
|
else
|
|
pWin->privCDC = 0;
|
|
|
|
// show and active this main window.
|
|
if (pWin->dwStyle & WS_VISIBLE) {
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
SendNotifyMessage ((HWND)pWin, MSG_SHOWWINDOW, SW_SHOWNORMAL, 0);
|
|
InvalidateRect ((HWND)pWin, NULL, TRUE);
|
|
dskSetActiveWindow (pWin);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dskHideGlobalControl (PMAINWIN pWin, int reason, LPARAM lParam)
|
|
{
|
|
int first = 0;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
lock_zi_for_read (__mg_zorder_info);
|
|
switch (nodes [pWin->idx_znode].flags & ZOF_TYPE_MASK) {
|
|
#if 0 /* no global ones */
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = __mg_zorder_info->first_global;
|
|
break;
|
|
#endif
|
|
case ZOF_TYPE_HIGHER:
|
|
first = __mg_zorder_info->first_topmost;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
first = __mg_zorder_info->first_normal;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
|
|
if (first > 0 && !(nodes [first].flags & ZOF_TF_MAINWIN)
|
|
&& (nodes [first].flags & ZOF_VISIBLE)) {
|
|
|
|
RECT rc = nodes [first].rc;
|
|
PMAINWIN pCurTop = (PMAINWIN) nodes [first].hwnd;
|
|
|
|
pCurTop->dwStyle &= ~WS_VISIBLE;
|
|
dskHideWindow (0, pCurTop->idx_znode);
|
|
dskSetPrimitiveChildren (pCurTop, FALSE);
|
|
SendNotifyMessage (pCurTop->hParent,
|
|
MSG_CHILDHIDDEN, reason, lParam);
|
|
|
|
dskScreenToClient (pCurTop->pMainWin, &rc, &rc);
|
|
InvalidateRect ((HWND)pCurTop->pMainWin, &rc, TRUE);
|
|
}
|
|
}
|
|
|
|
static int update_client_window_rgn (int cli, HWND hwnd)
|
|
{
|
|
CLIPRECT* crc = sg_UpdateRgn.head;
|
|
|
|
if (hwnd) {
|
|
while (crc) {
|
|
__mg_update_window (hwnd, crc->rc.left, crc->rc.top,
|
|
crc->rc.right, crc->rc.bottom);
|
|
crc = crc->next;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dskMoveToTopMost (PMAINWIN pWin, int reason, LPARAM lParam)
|
|
{
|
|
if (!pWin) return;
|
|
|
|
if (dskIsTopMost (pWin) && (pWin->dwStyle & WS_VISIBLE))
|
|
return;
|
|
|
|
dskHideGlobalControl (pWin, reason, lParam);
|
|
dskMove2Top (0, pWin->idx_znode);
|
|
|
|
if (!(pWin->dwStyle & WS_VISIBLE)) {
|
|
pWin->dwStyle |= WS_VISIBLE;
|
|
|
|
dskShowWindow (0, pWin->idx_znode);
|
|
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect ((HWND)pWin, NULL, TRUE);
|
|
}
|
|
else {
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
}
|
|
|
|
// activate this main window.
|
|
if (reason != RCTM_SHOWCTRL)
|
|
dskSetActiveWindow (pWin);
|
|
}
|
|
|
|
/* Since 5.0.0 */
|
|
static BOOL dskSetMainWindowAlwaysTop (PMAINWIN pWin, BOOL fSet)
|
|
{
|
|
if ((pWin->dwStyle & WS_ALWAYSTOP) && fSet)
|
|
return TRUE;
|
|
|
|
if (!(pWin->dwStyle & WS_ALWAYSTOP) && !fSet)
|
|
return TRUE;
|
|
|
|
if (dskSetZNodeAlwaysTop (0, pWin->idx_znode, fSet))
|
|
return FALSE;
|
|
|
|
if (fSet) {
|
|
pWin->dwStyle |= WS_ALWAYSTOP;
|
|
}
|
|
else {
|
|
pWin->dwStyle &= ~WS_ALWAYSTOP;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Since 5.0.6 */
|
|
static inline int dskSetMainWindowGestureFlags (PMAINWIN pWin, DWORD dwFlags)
|
|
{
|
|
if (dskSetZNodeGestureFlags (0, pWin->idx_znode, dwFlags))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Since 5.0.0 */
|
|
static int dskSetWindowMask (HWND pWin, const WINMASKINFO* mask_info)
|
|
{
|
|
FreeZOrderMaskRect (0, ((PMAINWIN)pWin)->idx_znode);
|
|
return AllocZOrderMaskRect (0, ((PMAINWIN)pWin)->idx_znode,
|
|
get_znode_flags_from_style ((PMAINWIN)pWin),
|
|
mask_info->rcs, mask_info->nr_rcs);
|
|
}
|
|
|
|
static void dskHideMainWindow (PMAINWIN pWin)
|
|
{
|
|
if (!(pWin->dwStyle & WS_VISIBLE))
|
|
return;
|
|
|
|
pWin->dwStyle &= ~WS_VISIBLE;
|
|
|
|
dskHideWindow (0, pWin->idx_znode);
|
|
}
|
|
|
|
// When destroy a main win, all main win which is covered by
|
|
// this destroying main win will be redraw.
|
|
//
|
|
// Functions which lead to call this function:
|
|
// DestroyWindow: destroy a visible window.
|
|
//
|
|
static void dskRemoveMainWindow (PMAINWIN pWin)
|
|
{
|
|
FreeZOrderMaskRect (0, pWin->idx_znode);
|
|
// Update window Z order list.
|
|
FreeZOrderNode (0, pWin->idx_znode, NULL);
|
|
|
|
#if 0 /* move to window.c since 5.0.0 */
|
|
// Handle main window hosting.
|
|
if (pWin->pHosting)
|
|
dskRemoveHostedMainWindow (pWin->pHosting, pWin);
|
|
#endif /* moved code */
|
|
|
|
/* houhh 20081127.*/
|
|
if ((pWin->dwExStyle & WS_EX_AUTOSECONDARYDC) && pWin->secondaryDC) {
|
|
#if 0 /* deprecated code */
|
|
DeleteSecondaryDC ((HWND)pWin);
|
|
#else /* deprecated code */
|
|
__mg_delete_secondary_dc (pWin);
|
|
#endif
|
|
pWin->update_secdc = NULL;
|
|
}
|
|
|
|
if (pWin->privCDC) {
|
|
#if 0 /* deprecated code */
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC) {
|
|
ReleaseSecondarySubDC (pWin->privCDC);
|
|
}
|
|
else {
|
|
if (pWin->secondaryDC)
|
|
ReleaseSecondarySubDC (pWin->privCDC);
|
|
else
|
|
DeletePrivateDC (pWin->privCDC);
|
|
}
|
|
#else /* deprecated code */
|
|
/* since 5.0.0, always call DeletePrivateDC */
|
|
DeletePrivateDC (pWin->privCDC);
|
|
#endif
|
|
pWin->privCDC = 0;
|
|
}
|
|
|
|
/* since 5.0.0, reset auto-repeat message if target window is the
|
|
main window being removed or it is contained in this main window */
|
|
if (checkAndGetMainWinIfWindow (sg_msgAutoRepeat.hwnd) == pWin) {
|
|
sg_msgAutoRepeat.hwnd = 0;
|
|
}
|
|
|
|
if (checkAndGetMainWinIfWindow (sg_hCaretWnd) == pWin) {
|
|
sg_hCaretWnd = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
|
|
static void dskForceCloseMenu (void)
|
|
{
|
|
ZORDERINFO* zi = __mg_zorder_info;
|
|
|
|
if (zi->cli_trackmenu < 0)
|
|
return;
|
|
|
|
srvForceCloseMenu (0);
|
|
}
|
|
|
|
static int dskStartTrackPopupMenu(PTRACKMENUINFO ptmi)
|
|
{
|
|
PTRACKMENUINFO plast;
|
|
|
|
if (sg_ptmi) {
|
|
plast = sg_ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
|
|
plast->next = ptmi;
|
|
ptmi->prev = plast;
|
|
ptmi->next = NULL;
|
|
}
|
|
else {
|
|
sg_ptmi = ptmi;
|
|
ptmi->next = NULL;
|
|
ptmi->prev = NULL;
|
|
}
|
|
|
|
if (PopupMenuTrackProc (ptmi, MSG_INITMENU, 0, 0))
|
|
return -1;
|
|
|
|
ptmi->idx_znode = srvStartTrackPopupMenu (0, &ptmi->rc, (HWND)ptmi,
|
|
0, 0, -1);
|
|
|
|
if (ptmi->idx_znode < 0) {
|
|
if (sg_ptmi == ptmi) {
|
|
sg_ptmi = NULL;
|
|
}
|
|
else {
|
|
plast = sg_ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
plast->prev->next = NULL;
|
|
plast = plast->prev;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
PopupMenuTrackProc (ptmi, MSG_SHOWMENU, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int dskEndTrackPopupMenu (PTRACKMENUINFO ptmi)
|
|
{
|
|
ZORDERINFO* zi = __mg_zorder_info;
|
|
PTRACKMENUINFO plast = NULL;
|
|
RECT rc;
|
|
RECT rcScr = GetScreenRect();
|
|
|
|
if (sg_ptmi == ptmi) {
|
|
sg_ptmi = NULL;
|
|
}
|
|
else {
|
|
plast = sg_ptmi;
|
|
while (plast->next) {
|
|
plast = plast->next;
|
|
}
|
|
plast->prev->next = NULL;
|
|
}
|
|
|
|
if (zi->cli_trackmenu == 0) {
|
|
srvEndTrackPopupMenu (0, ptmi->idx_znode);
|
|
}
|
|
|
|
PopupMenuTrackProc (ptmi, MSG_HIDEMENU, 0, 0);
|
|
|
|
PopupMenuTrackProc (ptmi, MSG_ENDTRACKMENU, 0, 0);
|
|
|
|
rc = ptmi->rc;
|
|
ptmi = sg_ptmi;
|
|
while (ptmi) {
|
|
if (DoesIntersect (&rc, &ptmi->rc)) {
|
|
SelectClipRect (HDC_SCREEN_SYS, &rc);
|
|
PopupMenuTrackProc (ptmi, MSG_SHOWMENU, 0, 0);
|
|
}
|
|
ptmi = ptmi->next;
|
|
}
|
|
SelectClipRect (HDC_SCREEN_SYS, &rcScr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* defiend _MGHAVE_MENU */
|
|
|
|
static void dskEnableWindow (PMAINWIN pWin, int flags)
|
|
{
|
|
|
|
if (dskEnableZOrderNode (0, pWin?pWin->idx_znode:0, flags))
|
|
return;
|
|
|
|
if ( (!(pWin->dwStyle & WS_DISABLED) && !flags)
|
|
|| ((pWin->dwStyle & WS_DISABLED) && flags) ) {
|
|
if (flags)
|
|
pWin->dwStyle &= ~WS_DISABLED;
|
|
else
|
|
pWin->dwStyle |= WS_DISABLED;
|
|
|
|
if (pWin->dwStyle & WS_DISABLED) {
|
|
if (__mg_captured_wnd &&
|
|
checkAndGetMainWinIfWindow (__mg_captured_wnd) == pWin)
|
|
__mg_captured_wnd = 0;
|
|
|
|
if (dskGetActiveWindow () == pWin) {
|
|
dskSetActiveWindow (NULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
}
|
|
}
|
|
|
|
static int dskMoveMainWindow (PMAINWIN pWin, const RECT* prcExpect)
|
|
{
|
|
RECT rcResult;
|
|
|
|
SendAsyncMessage ((HWND)pWin, MSG_CHANGESIZE,
|
|
(WPARAM)(prcExpect), (LPARAM)(&rcResult));
|
|
|
|
return dskMoveWindow (0, pWin->idx_znode, HDC_INVALID, &rcResult);
|
|
}
|
|
|
|
static int dskMoveGlobalControl (PMAINWIN pCtrl, RECT* prcExpect)
|
|
{
|
|
RECT newWinRect, rcResult;
|
|
int ret;
|
|
|
|
SendAsyncMessage ((HWND)pCtrl, MSG_CHANGESIZE,
|
|
(WPARAM)(prcExpect), (LPARAM)(&rcResult));
|
|
dskClientToScreen ((PMAINWIN)(pCtrl->hParent), prcExpect, &newWinRect);
|
|
|
|
ret = dskMoveWindow (0, pCtrl->idx_znode, HDC_INVALID, &newWinRect);
|
|
|
|
if (ret == 0 && pCtrl->dwStyle & WS_VISIBLE) {
|
|
SendAsyncMessage ((HWND)pCtrl, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect ((HWND)pCtrl, NULL, TRUE);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*********************** Desktop window support ******************************/
|
|
PMAINWIN gui_GetMainWindowPtrUnderPoint (int x, int y)
|
|
{
|
|
int slot;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
slot = get_znode_at_point (__mg_zorder_info, nodes, x, y);
|
|
|
|
if (slot == 0)
|
|
return NULL;
|
|
else
|
|
return (PMAINWIN)(nodes[slot].hwnd);
|
|
}
|
|
|
|
static int HandleSpecialKey (int scancode)
|
|
{
|
|
switch (scancode) {
|
|
case SCANCODE_BACKSPACE:
|
|
ExitGUISafely (-1);
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT KeyMessageHandler (UINT message, int scancode, DWORD status)
|
|
{
|
|
static int mg_altdown = 0;
|
|
static int mg_modal = 0;
|
|
int next_node;
|
|
|
|
if ((message == MSG_KEYDOWN) && (status & KS_ALT) && (status & KS_CTRL))
|
|
return HandleSpecialKey (scancode);
|
|
|
|
if (scancode == SCANCODE_LEFTALT ||
|
|
scancode == SCANCODE_RIGHTALT) {
|
|
if (message == MSG_KEYDOWN) {
|
|
mg_altdown = 1;
|
|
return 0;
|
|
}
|
|
else {
|
|
mg_altdown = 0;
|
|
if (mg_modal == 1) {
|
|
mg_modal = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mg_altdown) {
|
|
|
|
if (message == MSG_KEYDOWN) {
|
|
if( scancode == SCANCODE_TAB) {
|
|
|
|
mg_modal = 1;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
next_node =
|
|
get_next_activable_mainwin (__mg_zorder_info,
|
|
__mg_zorder_info->active_win);
|
|
|
|
if (next_node) {
|
|
dskMove2Top (0, next_node);
|
|
dskSetActiveZOrderNode (__mg_zorder_info, 0, next_node);
|
|
}
|
|
return 0;
|
|
}
|
|
else if (scancode == SCANCODE_ESCAPE) {
|
|
|
|
mg_modal = 1;
|
|
|
|
if (__mg_zorder_info->active_win) {
|
|
__mg_post_msg_by_znode (__mg_zorder_info,
|
|
__mg_zorder_info->active_win,
|
|
MSG_CLOSE, 0, 0);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else if (mg_modal == 1)
|
|
return 0;
|
|
}
|
|
|
|
if (scancode == SCANCODE_LEFTALT
|
|
|| scancode == SCANCODE_RIGHTALT || mg_altdown) {
|
|
if (message == MSG_KEYDOWN)
|
|
message = MSG_SYSKEYDOWN;
|
|
else {
|
|
message = MSG_SYSKEYUP;
|
|
mg_altdown = 0;
|
|
}
|
|
}
|
|
|
|
#if 0 /* since 5.0.0, deprecated code */
|
|
|
|
#ifndef _MGRM_THREADS
|
|
if (__mg_ime_wnd
|
|
&& message != MSG_SYSKEYDOWN && message != MSG_SYSKEYUP) {
|
|
if (dskHandleKeyHooks (__mg_ime_wnd,
|
|
message, (WPARAM)scancode, (LPARAM)status) == HOOK_GOON)
|
|
PostMessage (__mg_ime_wnd,
|
|
message, (WPARAM)scancode, (LPARAM)status);
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
else if (__mg_ime_wnd && __mg_zorder_info->active_win) {
|
|
if (dskHandleKeyHooks (__mg_ime_wnd,
|
|
message, (WPARAM)scancode, (LPARAM)status) == HOOK_GOON)
|
|
PostMessage (__mg_ime_wnd,
|
|
message, (WPARAM)scancode, (LPARAM)status);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
if (__mg_zorder_info->active_win) {
|
|
if (dskHandleKeyHooks ((HWND)dskGetActiveWindow(),
|
|
message, (WPARAM)scancode, (LPARAM)status) == HOOK_GOON) {
|
|
__mg_post_msg_by_znode (__mg_zorder_info,
|
|
__mg_zorder_info->active_win, message,
|
|
(WPARAM)scancode, (LPARAM)status);
|
|
}
|
|
}
|
|
else {
|
|
if (dskHandleKeyHooks (HWND_DESKTOP, message,
|
|
(WPARAM)scancode, (LPARAM)status) == HOOK_GOON) {
|
|
SendMessage (HWND_DESKTOP, MSG_DT_KEYOFF + message,
|
|
(WPARAM)scancode, (LPARAM)status);
|
|
}
|
|
}
|
|
|
|
#else /* since 5.0.0, deprecated code */
|
|
|
|
#ifndef _MGRM_THREADS
|
|
if (__mg_ime_wnd &&
|
|
message != MSG_SYSKEYDOWN && message != MSG_SYSKEYUP) {
|
|
PostMessage (__mg_ime_wnd, message, (WPARAM)scancode, (LPARAM)status);
|
|
return 0;
|
|
}
|
|
#else
|
|
else if (__mg_ime_wnd && __mg_zorder_info->active_win) {
|
|
PostMessage (__mg_ime_wnd,
|
|
message, (WPARAM)scancode, (LPARAM)status);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
if (__mg_zorder_info->active_win) {
|
|
__mg_post_msg_by_znode (__mg_zorder_info,
|
|
__mg_zorder_info->active_win,
|
|
message, (WPARAM)scancode, (LPARAM)status);
|
|
}
|
|
else {
|
|
SendMessage (HWND_DESKTOP, MSG_DT_KEYOFF + message,
|
|
(WPARAM)scancode, (LPARAM)status);
|
|
}
|
|
|
|
#endif /* since 5.0.0: do not handle hook function here */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PMAINWIN _mgs_button_down_main_window = NULL;
|
|
static PMAINWIN _mgs_old_under_p = NULL;
|
|
|
|
#define DOWN_BUTTON_NONE 0x0000
|
|
#define DOWN_BUTTON_LEFT 0x0001
|
|
#define DOWN_BUTTON_RIGHT 0x0002
|
|
#define DOWN_BUTTON_MIDDLE 0x0004
|
|
#define DOWN_BUTTON_ANY 0x000F
|
|
|
|
static DWORD _mgs_down_buttons = 0;
|
|
|
|
/* defined in ../gui/window.c */
|
|
extern void __mg_reset_mainwin_capture_info (PCONTROL ctrl);
|
|
|
|
void __mg_reset_desktop_capture_info (PMAINWIN pWin)
|
|
{
|
|
_mgs_old_under_p = NULL;
|
|
|
|
if (!__mg_ime_wnd || (HWND)pWin != __mg_ime_wnd) {
|
|
_mgs_button_down_main_window = NULL;
|
|
_mgs_down_buttons = DOWN_BUTTON_NONE;
|
|
}
|
|
|
|
if ((HWND)pWin == __mg_captured_wnd)
|
|
__mg_captured_wnd = 0;
|
|
|
|
__mg_reset_mainwin_capture_info ((PCONTROL)pWin);
|
|
}
|
|
|
|
static HWND DesktopSetCapture (HWND hwnd)
|
|
{
|
|
HWND hTemp;
|
|
|
|
_mgs_old_under_p = NULL;
|
|
_mgs_button_down_main_window = checkAndGetMainWinIfWindow (hwnd);
|
|
_mgs_down_buttons = DOWN_BUTTON_NONE;
|
|
|
|
hTemp = __mg_captured_wnd;
|
|
__mg_captured_wnd = hwnd;
|
|
return hTemp;
|
|
}
|
|
|
|
static LRESULT MouseMessageHandler (UINT message, WPARAM flags, int x, int y)
|
|
{
|
|
PMAINWIN pUnderPointer;
|
|
PMAINWIN pCtrlPtrIn;
|
|
|
|
if (__mg_captured_wnd) {
|
|
PostMessage (__mg_captured_wnd, message,
|
|
flags | KS_CAPTURED, MAKELONG (x, y));
|
|
return 0;
|
|
}
|
|
|
|
pCtrlPtrIn = gui_GetMainWindowPtrUnderPoint (x, y);
|
|
|
|
#if 0 /* since 5.0.0, do not handle hook function here */
|
|
if (dskHandleMouseHooks ((HWND)pCtrlPtrIn,
|
|
message, flags, MAKELONG (x, y)) == HOOK_STOP)
|
|
return 0;
|
|
#endif /* since 5.0.0, do not handle hook function here */
|
|
|
|
if (pCtrlPtrIn && pCtrlPtrIn->WinType == TYPE_CONTROL) {
|
|
pUnderPointer = pCtrlPtrIn->pMainWin;
|
|
}
|
|
else {
|
|
pUnderPointer = pCtrlPtrIn;
|
|
pCtrlPtrIn = NULL;
|
|
}
|
|
|
|
switch (message) {
|
|
case MSG_MOUSEMOVE:
|
|
if (_mgs_button_down_main_window) {
|
|
PostMessage ((HWND)_mgs_button_down_main_window,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
}
|
|
else {
|
|
if (_mgs_old_under_p != pUnderPointer) {
|
|
if (_mgs_old_under_p) {
|
|
PostMessage ((HWND)_mgs_old_under_p,
|
|
MSG_MOUSEMOVEIN, FALSE, (LPARAM)pUnderPointer);
|
|
PostMessage ((HWND)_mgs_old_under_p,
|
|
MSG_NCMOUSEMOVE, HT_OUT, MAKELONG (x, y));
|
|
}
|
|
if (pUnderPointer)
|
|
PostMessage ((HWND)pUnderPointer,
|
|
MSG_MOUSEMOVEIN, TRUE, (LPARAM)_mgs_old_under_p);
|
|
else
|
|
SetCursor (GetSystemCursor (IDC_ARROW));
|
|
|
|
_mgs_old_under_p = pUnderPointer;
|
|
}
|
|
|
|
if (pUnderPointer) {
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
HCURSOR def_cursor = GetDefaultCursor ();
|
|
|
|
if (def_cursor)
|
|
SetCursor (def_cursor);
|
|
}
|
|
else
|
|
PostMessage ((HWND)pUnderPointer,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
}
|
|
else {
|
|
HCURSOR def_cursor = GetDefaultCursor ();
|
|
|
|
if (def_cursor)
|
|
SetCursor (def_cursor);
|
|
PostMessage (HWND_DESKTOP, MSG_DT_MOUSEMOVE,
|
|
flags, MAKELONG (x, y));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONDOWN:
|
|
case MSG_RBUTTONDOWN:
|
|
case MSG_MBUTTONDOWN:
|
|
if (_mgs_button_down_main_window) {
|
|
PostMessage ((HWND)_mgs_button_down_main_window,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
if (message == MSG_LBUTTONDOWN)
|
|
_mgs_down_buttons |= DOWN_BUTTON_LEFT;
|
|
else if (message == MSG_RBUTTONDOWN)
|
|
_mgs_down_buttons |= DOWN_BUTTON_RIGHT;
|
|
else
|
|
_mgs_down_buttons |= DOWN_BUTTON_MIDDLE;
|
|
}
|
|
else if (pUnderPointer) {
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
Ping ();
|
|
break;
|
|
}
|
|
|
|
if (pCtrlPtrIn == NULL) {
|
|
if (!dskIsTopMost (pUnderPointer)) {
|
|
dskMoveToTopMost (pUnderPointer,
|
|
RCTM_CLICK, MAKELONG (x, y));
|
|
}
|
|
|
|
if (pUnderPointer != dskSetActiveWindow (pUnderPointer))
|
|
SendNotifyMessage ((HWND) pUnderPointer,
|
|
MSG_MOUSEACTIVE, 0, 0);
|
|
}
|
|
|
|
PostMessage ((HWND)pUnderPointer, message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
|
|
_mgs_button_down_main_window = pUnderPointer;
|
|
if (message == MSG_LBUTTONDOWN)
|
|
_mgs_down_buttons = DOWN_BUTTON_LEFT;
|
|
else if (message == MSG_RBUTTONDOWN)
|
|
_mgs_down_buttons = DOWN_BUTTON_RIGHT;
|
|
else
|
|
_mgs_down_buttons = DOWN_BUTTON_MIDDLE;
|
|
}
|
|
else {
|
|
dskSetActiveWindow (NULL);
|
|
PostMessage (HWND_DESKTOP, message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
_mgs_button_down_main_window = NULL;
|
|
_mgs_down_buttons = DOWN_BUTTON_NONE;
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONUP:
|
|
case MSG_RBUTTONUP:
|
|
case MSG_MBUTTONUP:
|
|
if (_mgs_down_buttons == DOWN_BUTTON_LEFT &&
|
|
message != MSG_LBUTTONUP) {
|
|
break;
|
|
}
|
|
if (_mgs_down_buttons == DOWN_BUTTON_RIGHT &&
|
|
message != MSG_RBUTTONUP) {
|
|
break;
|
|
}
|
|
if (_mgs_down_buttons == DOWN_BUTTON_MIDDLE &&
|
|
message != MSG_MBUTTONUP) {
|
|
break;
|
|
}
|
|
|
|
if (_mgs_button_down_main_window) {
|
|
PostMessage ((HWND)_mgs_button_down_main_window,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
if (message == MSG_LBUTTONUP)
|
|
_mgs_down_buttons &= ~DOWN_BUTTON_LEFT;
|
|
else if (message == MSG_RBUTTONUP)
|
|
_mgs_down_buttons &= ~DOWN_BUTTON_RIGHT;
|
|
else
|
|
_mgs_down_buttons &= ~DOWN_BUTTON_MIDDLE;
|
|
|
|
if (!(_mgs_down_buttons & DOWN_BUTTON_ANY)) {
|
|
_mgs_button_down_main_window = NULL;
|
|
_mgs_down_buttons = DOWN_BUTTON_NONE;
|
|
}
|
|
}
|
|
else {
|
|
/* fixed bug 4961: for deal with when _mgs_button_down_main_window was reset,
|
|
* but there real has a mouse up message. by humingming 2010.9.1
|
|
*/
|
|
if (pUnderPointer == NULL) {
|
|
PostMessage (HWND_DESKTOP,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
}
|
|
else {
|
|
if ((pUnderPointer->dwStyle & WS_DISABLED)) {
|
|
break;
|
|
}
|
|
else {
|
|
PostMessage((HWND)pUnderPointer,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONDBLCLK:
|
|
case MSG_RBUTTONDBLCLK:
|
|
case MSG_MBUTTONDBLCLK:
|
|
if (_mgs_button_down_main_window) {
|
|
PostMessage ((HWND)_mgs_button_down_main_window,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
if (message == MSG_LBUTTONDBLCLK)
|
|
_mgs_down_buttons |= DOWN_BUTTON_LEFT;
|
|
else if (message == MSG_RBUTTONDBLCLK)
|
|
_mgs_down_buttons |= DOWN_BUTTON_RIGHT;
|
|
else
|
|
_mgs_down_buttons |= DOWN_BUTTON_MIDDLE;
|
|
}
|
|
else if (pUnderPointer) {
|
|
PostMessage ((HWND)pUnderPointer,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
_mgs_button_down_main_window = pUnderPointer;
|
|
if (message == MSG_LBUTTONDBLCLK)
|
|
_mgs_down_buttons = DOWN_BUTTON_LEFT;
|
|
else if (message == MSG_RBUTTONDBLCLK)
|
|
_mgs_down_buttons = DOWN_BUTTON_RIGHT;
|
|
else
|
|
_mgs_down_buttons = DOWN_BUTTON_MIDDLE;
|
|
}
|
|
else {
|
|
PostMessage (HWND_DESKTOP,
|
|
message + MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (x, y));
|
|
_mgs_button_down_main_window = NULL;
|
|
_mgs_down_buttons = DOWN_BUTTON_NONE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
typedef struct _DRAGDROPINFO {
|
|
HWND hwnd;
|
|
RECT rc;
|
|
|
|
int location;
|
|
int last_x, last_y;
|
|
} DRAGDROPINFO;
|
|
|
|
static DRAGDROPINFO _dd_info;
|
|
|
|
#ifndef _MGRM_THREADS
|
|
|
|
inline static void lock_zorder_info (void) { }
|
|
inline static void unlock_zorder_info (void) { }
|
|
|
|
#else /* not define _MGRM_THREADS */
|
|
|
|
static void lock_zorder_info (void)
|
|
{
|
|
PMAINWIN pWin = NULL;
|
|
int level, slot;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
for (level = 0; level < NR_ZORDER_LEVELS; level++) {
|
|
slot = __mg_zorder_info->first_in_levels[level];
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin)
|
|
pthread_mutex_lock (&pWin->pGCRInfo->lock);
|
|
}
|
|
}
|
|
|
|
#if 0 /* deprected code */
|
|
static int fixed_slots [] = { ZNIDX_SCREENLOCK, ZNIDX_DOCKER,
|
|
ZNIDX_LAUNCHER };
|
|
|
|
/* Since 5.0.0 */
|
|
for (slot = 0; slot < TABLESIZE(fixed_slots); slot++) {
|
|
pWin = (PMAINWIN)(nodes[fixed_slots[slot]].hwnd);
|
|
if (pWin)
|
|
pthread_mutex_lock (&pWin->pGCRInfo->lock);
|
|
}
|
|
|
|
slot = __mg_zorder_info->first_topmost;
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin)
|
|
pthread_mutex_lock (&pWin->pGCRInfo->lock);
|
|
}
|
|
|
|
slot = __mg_zorder_info->first_normal;
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin)
|
|
pthread_mutex_lock (&pWin->pGCRInfo->lock);
|
|
}
|
|
#endif /* deprected code */
|
|
}
|
|
|
|
static void unlock_zorder_info (void)
|
|
{
|
|
PMAINWIN pWin;
|
|
int level, slot;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
for (level = 0; level < NR_ZORDER_LEVELS; level++) {
|
|
slot = __mg_zorder_info->first_in_levels[level];
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin)
|
|
pthread_mutex_unlock (&pWin->pGCRInfo->lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* define _MGRM_THREADS */
|
|
|
|
static int dskStartDragWindow (PMAINWIN pWin, const DRAGINFO* drag_info)
|
|
{
|
|
if (!(pWin->dwStyle & WS_VISIBLE))
|
|
return -1;
|
|
|
|
if (_dd_info.hwnd != 0)
|
|
return -1;
|
|
|
|
_mgs_old_under_p = NULL;
|
|
_mgs_button_down_main_window = NULL;
|
|
_mgs_down_buttons = 0;
|
|
|
|
lock_zorder_info ();
|
|
|
|
_dd_info.hwnd = (HWND)pWin;
|
|
_dd_info.rc.left = pWin->left;
|
|
_dd_info.rc.top = pWin->top;
|
|
_dd_info.rc.right = pWin->right;
|
|
_dd_info.rc.bottom = pWin->bottom;
|
|
_dd_info.location = drag_info->location;
|
|
_dd_info.last_x = drag_info->init_x;
|
|
_dd_info.last_y = drag_info->init_y;
|
|
|
|
switch (_dd_info.location) {
|
|
case HT_CAPTION:
|
|
//SetDefaultCursor (GetSystemCursor (IDC_MOVE));
|
|
SetCursor (GetSystemCursor (IDC_MOVE));
|
|
break;
|
|
case HT_BORDER_TOP:
|
|
case HT_BORDER_BOTTOM:
|
|
//SetDefaultCursor (GetSystemCursor (IDC_SIZENS));
|
|
SetCursor (GetSystemCursor (IDC_SIZENS));
|
|
break;
|
|
case HT_BORDER_LEFT:
|
|
case HT_BORDER_RIGHT:
|
|
//SetDefaultCursor (GetSystemCursor (IDC_SIZEWE));
|
|
SetCursor (GetSystemCursor (IDC_SIZEWE));
|
|
break;
|
|
case HT_CORNER_TL:
|
|
case HT_CORNER_BR:
|
|
//SetDefaultCursor (GetSystemCursor (IDC_SIZENWSE));
|
|
SetCursor (GetSystemCursor (IDC_SIZENWSE));
|
|
break;
|
|
case HT_CORNER_BL:
|
|
case HT_CORNER_TR:
|
|
//SetDefaultCursor (GetSystemCursor (IDC_SIZENESW));
|
|
SetCursor (GetSystemCursor (IDC_SIZENESW));
|
|
break;
|
|
default:
|
|
_WRN_PRINTF ("bad location\n");
|
|
break;
|
|
}
|
|
|
|
SetPenColor (HDC_SCREEN_SYS, PIXEL_lightwhite);
|
|
FocusRect (HDC_SCREEN_SYS, _dd_info.rc.left, _dd_info.rc.top,
|
|
_dd_info.rc.right, _dd_info.rc.bottom);
|
|
SyncUpdateDC (HDC_SCREEN_SYS);
|
|
return 0;
|
|
}
|
|
|
|
static int dskCancelDragWindow (PMAINWIN pWin)
|
|
{
|
|
RECT rcScr = GetScreenRect();
|
|
|
|
if (!(pWin->dwStyle & WS_VISIBLE))
|
|
return -1;
|
|
|
|
if (_dd_info.hwnd == 0 || _dd_info.hwnd != (HWND)pWin)
|
|
return -1;
|
|
|
|
_dd_info.hwnd = (HWND)-1;
|
|
unlock_zorder_info ();
|
|
SelectClipRect (HDC_SCREEN_SYS, &rcScr);
|
|
return 0;
|
|
}
|
|
|
|
static int do_drag_drop_window (UINT msg, int x, int y)
|
|
{
|
|
if (_dd_info.hwnd == 0)
|
|
return 0;
|
|
|
|
if (msg == MSG_MOUSEMOVE) {
|
|
SetPenColor (HDC_SCREEN_SYS, PIXEL_lightwhite);
|
|
FocusRect (HDC_SCREEN_SYS, _dd_info.rc.left, _dd_info.rc.top,
|
|
_dd_info.rc.right, _dd_info.rc.bottom);
|
|
SyncUpdateDC (HDC_SCREEN_SYS);
|
|
|
|
switch (_dd_info.location) {
|
|
case HT_CAPTION:
|
|
OffsetRect (&_dd_info.rc,
|
|
x - _dd_info.last_x,
|
|
y - _dd_info.last_y);
|
|
break;
|
|
|
|
case HT_BORDER_TOP:
|
|
_dd_info.rc.top += y - _dd_info.last_y;
|
|
break;
|
|
|
|
case HT_BORDER_BOTTOM:
|
|
_dd_info.rc.bottom += y - _dd_info.last_y;
|
|
break;
|
|
|
|
case HT_BORDER_LEFT:
|
|
_dd_info.rc.left += x - _dd_info.last_x;
|
|
break;
|
|
|
|
case HT_BORDER_RIGHT:
|
|
_dd_info.rc.right += x - _dd_info.last_x;
|
|
break;
|
|
|
|
case HT_CORNER_TL:
|
|
_dd_info.rc.left += x - _dd_info.last_x;
|
|
_dd_info.rc.top += y - _dd_info.last_y;
|
|
break;
|
|
|
|
case HT_CORNER_TR:
|
|
_dd_info.rc.right += x - _dd_info.last_x;
|
|
_dd_info.rc.top += y - _dd_info.last_y;
|
|
break;
|
|
|
|
case HT_CORNER_BL:
|
|
_dd_info.rc.left += x - _dd_info.last_x;
|
|
_dd_info.rc.bottom += y - _dd_info.last_y;
|
|
break;
|
|
|
|
case HT_CORNER_BR:
|
|
_dd_info.rc.right += x - _dd_info.last_x;
|
|
_dd_info.rc.bottom += y - _dd_info.last_y;
|
|
break;
|
|
|
|
default:
|
|
_WRN_PRINTF ("bad location\n");
|
|
break;
|
|
}
|
|
|
|
FocusRect (HDC_SCREEN_SYS, _dd_info.rc.left, _dd_info.rc.top,
|
|
_dd_info.rc.right, _dd_info.rc.bottom);
|
|
SyncUpdateDC (HDC_SCREEN_SYS);
|
|
|
|
_dd_info.last_x = x;
|
|
_dd_info.last_y = y;
|
|
}
|
|
else {
|
|
RECT rcScr = GetScreenRect();
|
|
|
|
SetPenColor (HDC_SCREEN_SYS, PIXEL_lightwhite);
|
|
FocusRect (HDC_SCREEN_SYS, _dd_info.rc.left, _dd_info.rc.top,
|
|
_dd_info.rc.right, _dd_info.rc.bottom);
|
|
SyncUpdateDC (HDC_SCREEN_SYS);
|
|
|
|
/* post MSG_WINDOWDROPPED to the target window */
|
|
SendNotifyMessage (_dd_info.hwnd, MSG_WINDOWDROPPED,
|
|
MAKELONG (_dd_info.rc.left, _dd_info.rc.top),
|
|
MAKELONG (_dd_info.rc.right, _dd_info.rc.bottom));
|
|
unlock_zorder_info ();
|
|
SelectClipRect (HDC_SCREEN_SYS, &rcScr);
|
|
|
|
if (_dd_info.hwnd != (HWND)gui_GetMainWindowPtrUnderPoint (x, y))
|
|
SetDefaultCursor (GetSystemCursor (IDC_ARROW));
|
|
_dd_info.hwnd = 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static LRESULT WindowMessageHandler(UINT message, PMAINWIN pWin, LPARAM lParam)
|
|
{
|
|
LRESULT lRet = 0;
|
|
|
|
/* cancel the current drag and drop operation */
|
|
do_drag_drop_window (message, 0, 0);
|
|
|
|
switch (message) {
|
|
case MSG_ADDNEWMAINWIN:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
return dskAddNewMainWindow(pWin);
|
|
|
|
case MSG_REMOVEMAINWIN:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskRemoveMainWindow(pWin);
|
|
__mg_reset_desktop_capture_info (pWin);
|
|
return 0;
|
|
|
|
case MSG_MOVETOTOPMOST:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskMoveToTopMost(pWin, RCTM_MESSAGE, 0);
|
|
return 0;
|
|
|
|
case MSG_SHOWMAINWIN:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskShowMainWindow(pWin, TRUE);
|
|
return 0;
|
|
|
|
case MSG_HIDEMAINWIN:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskHideMainWindow (pWin);
|
|
__mg_reset_desktop_capture_info (pWin);
|
|
return 0;
|
|
|
|
case MSG_MOVEMAINWIN:
|
|
if (pWin->WinType == TYPE_CONTROL)
|
|
lRet = (LRESULT)dskMoveGlobalControl (pWin, (RECT*)lParam);
|
|
else {
|
|
lRet = (LRESULT)dskMoveMainWindow (pWin, (RECT*)lParam);
|
|
}
|
|
return lRet;
|
|
|
|
case MSG_GETACTIVEMAIN:
|
|
return (LRESULT)dskGetActiveWindow();
|
|
|
|
case MSG_SETACTIVEMAIN:
|
|
lRet = (LRESULT)dskSetActiveWindow (pWin);
|
|
return lRet;
|
|
|
|
case MSG_GETCAPTURE:
|
|
return (LRESULT)__mg_captured_wnd;
|
|
|
|
case MSG_SETCAPTURE:
|
|
return (LRESULT)DesktopSetCapture ((HWND)pWin);
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
case MSG_TRACKPOPUPMENU:
|
|
return dskStartTrackPopupMenu((PTRACKMENUINFO)lParam);
|
|
|
|
case MSG_ENDTRACKMENU:
|
|
return dskEndTrackPopupMenu((PTRACKMENUINFO)lParam);
|
|
|
|
case MSG_CLOSEMENU:
|
|
return dskCloseMenu ();
|
|
#endif
|
|
|
|
case MSG_SCROLLMAINWIN:
|
|
lRet = dskScrollMainWindow (pWin, (PSCROLLWINDOWINFO)lParam);
|
|
return lRet;
|
|
|
|
case MSG_CARET_CREATE:
|
|
sg_hCaretWnd = (HWND)pWin;
|
|
sg_uCaretBTime = pWin->pCaretInfo->uTime;
|
|
return 0;
|
|
|
|
case MSG_CARET_DESTROY:
|
|
sg_hCaretWnd = 0;
|
|
return 0;
|
|
|
|
case MSG_ENABLEMAINWIN:
|
|
dskEnableWindow (pWin, lParam);
|
|
return 0;
|
|
|
|
case MSG_ISENABLED:
|
|
return !(pWin->dwStyle & WS_DISABLED);
|
|
|
|
case MSG_SETWINCURSOR: {
|
|
HCURSOR old = pWin->hCursor;
|
|
|
|
pWin->hCursor = (HCURSOR)lParam;
|
|
return (LRESULT)old;
|
|
}
|
|
|
|
case MSG_GETNEXTMAINWIN: {
|
|
ZORDERINFO* zi = __mg_zorder_info;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(zi);
|
|
HWND hwnd = HWND_NULL;
|
|
int from;
|
|
|
|
if (pWin) {
|
|
from = pWin->idx_znode;
|
|
}
|
|
else {
|
|
from = 0;
|
|
}
|
|
|
|
lock_zi_for_read (zi);
|
|
|
|
from = __kernel_get_next_znode (zi, from);
|
|
while (from > 0) {
|
|
hwnd = nodes[from].hwnd;
|
|
|
|
if ((pWin = checkAndGetMainWinIfMainWin (hwnd)) &&
|
|
!(pWin->dwExStyle & WS_EX_CTRLASMAINWIN)) {
|
|
break;
|
|
}
|
|
|
|
from = __kernel_get_next_znode (zi, from);
|
|
}
|
|
|
|
unlock_zi_for_read (zi);
|
|
return (LRESULT)hwnd;
|
|
}
|
|
|
|
case MSG_DUMPZORDER:
|
|
dskDumpZOrder (__mg_zorder_info);
|
|
break;
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_SETAUTOREPEAT:
|
|
sg_msgAutoRepeat = *(const MSG*)lParam;
|
|
/* start auto-repeat after 300ms */
|
|
sg_msgAutoRepeat.time = __mg_tick_counter + (__mg_timeout_usec/10000);
|
|
break;
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_SETALWAYSTOP:
|
|
return dskSetMainWindowAlwaysTop (pWin, (BOOL)lParam);
|
|
|
|
/* Since 5.0.6 */
|
|
case MSG_SETGESTUREFLAGS:
|
|
return dskSetMainWindowGestureFlags (pWin, (DWORD)lParam);
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_SETWINDOWMASK:
|
|
return dskSetWindowMask (pWin, (WINMASKINFO*)lParam);
|
|
|
|
case MSG_SHOWGLOBALCTRL:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskMoveGlobalControl (pWin, (RECT*)&(pWin->left));
|
|
dskMoveToTopMost (pWin, RCTM_SHOWCTRL, 0);
|
|
dskSetPrimitiveChildren (pWin, TRUE);
|
|
break;
|
|
|
|
case MSG_HIDEGLOBALCTRL:
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
dskHideMainWindow (pWin);
|
|
dskSetPrimitiveChildren (pWin, FALSE);
|
|
break;
|
|
|
|
case MSG_STARTDRAGWIN:
|
|
return dskStartDragWindow (pWin, (DRAGINFO*)lParam);
|
|
|
|
case MSG_CANCELDRAGWIN:
|
|
return dskCancelDragWindow (pWin);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
#define IDM_REDRAWBG MINID_RESERVED
|
|
#define IDM_CLOSEALLWIN (MINID_RESERVED + 1)
|
|
#define IDM_ENDSESSION (MINID_RESERVED + 2)
|
|
|
|
#define IDM_FIRSTWINDOW (MINID_RESERVED + 101)
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
static HMENU dskCreateWindowSubMenu (void)
|
|
{
|
|
HMENU hmnu;
|
|
MENUITEMINFO mii;
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = 0;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_WINDOW);
|
|
|
|
hmnu = CreatePopupMenu (&mii);
|
|
return hmnu;
|
|
}
|
|
|
|
static HMENU dskCreateDesktopMenu (void)
|
|
{
|
|
HMENU hmnu;
|
|
MENUITEMINFO mii;
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = 0;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_START);
|
|
|
|
hmnu = CreatePopupMenu (&mii);
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = IDM_REDRAWBG;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_REFRESH);
|
|
InsertMenuItem (hmnu, 0, TRUE, &mii);
|
|
|
|
mii.type = MFT_STRING;
|
|
mii.id = IDM_CLOSEALLWIN;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_CLOSEALLWIN);
|
|
InsertMenuItem (hmnu, 1, TRUE, &mii);
|
|
|
|
mii.type = MFT_STRING;
|
|
mii.id = IDM_ENDSESSION;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_ENDSESSION);
|
|
InsertMenuItem (hmnu, 2, TRUE, &mii);
|
|
|
|
mii.type = MFT_STRING;
|
|
mii.id = 0;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_WINDOW);
|
|
mii.hsubmenu = dskCreateWindowSubMenu();
|
|
InsertMenuItem (hmnu, 3, TRUE, &mii);
|
|
|
|
mii.type = MFT_SEPARATOR;
|
|
mii.id = 0;
|
|
mii.typedata = 0;
|
|
mii.hsubmenu = 0;
|
|
InsertMenuItem(hmnu, 4, TRUE, &mii);
|
|
|
|
return hmnu;
|
|
}
|
|
|
|
static void dskUpdateDesktopMenu (HMENU hDesktopMenu)
|
|
{
|
|
MENUITEMINFO mii;
|
|
HMENU hWinMenu;
|
|
int nCount, iPos;
|
|
PMAINWIN pWin;
|
|
int id;
|
|
int level, slot;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
hWinMenu = GetSubMenu (hDesktopMenu, 3);
|
|
nCount = GetMenuItemCount (hWinMenu);
|
|
|
|
for (iPos = nCount; iPos > 0; iPos--)
|
|
DeleteMenu (hWinMenu, iPos - 1, MF_BYPOSITION);
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
|
|
id = IDM_FIRSTWINDOW;
|
|
iPos = 0;
|
|
|
|
for (level = 0; level < NR_ZORDER_LEVELS; level++) {
|
|
BOOL inserted;
|
|
|
|
inserted = FALSE;
|
|
slot = __mg_zorder_info->first_in_levels[level];
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin && pWin->WinType == TYPE_MAINWIN) {
|
|
if (nodes[slot].flags & ZOF_VISIBLE &&
|
|
!(nodes[slot].flags & ZOF_DISABLED))
|
|
mii.state = MFS_ENABLED;
|
|
else
|
|
mii.state = MFS_DISABLED;
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
|
|
mii.type = MFT_STRING;
|
|
mii.id = id;
|
|
mii.typedata = (DWORD)pWin->spCaption;
|
|
mii.itemdata = (DWORD)pWin;
|
|
InsertMenuItem (hWinMenu, iPos, TRUE, &mii);
|
|
|
|
id++;
|
|
iPos++;
|
|
|
|
inserted = TRUE;
|
|
}
|
|
|
|
if (inserted && level < (NR_ZORDER_LEVELS - 1) &&
|
|
__mg_zorder_info->first_in_levels[level+1] > 0) {
|
|
mii.type = MFT_SEPARATOR;
|
|
mii.state = 0;
|
|
mii.id = 0;
|
|
mii.typedata = 0;
|
|
InsertMenuItem(hWinMenu, iPos, TRUE, &mii);
|
|
iPos ++;
|
|
}
|
|
}
|
|
|
|
nCount = GetMenuItemCount (hDesktopMenu);
|
|
for (iPos = nCount; iPos > 5; iPos --)
|
|
DeleteMenu (hDesktopMenu, iPos - 1, MF_BYPOSITION);
|
|
|
|
dsk_ops->customize_desktop_menu (dt_context, hDesktopMenu, 5);
|
|
}
|
|
#endif
|
|
|
|
static void close_all_main_window (void)
|
|
{
|
|
int level, slot;
|
|
PMAINWIN pWin;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
|
|
for (level = 0; level < NR_ZORDER_LEVELS; level++) {
|
|
slot = __mg_zorder_info->first_in_levels[level];
|
|
for (; slot > 0; slot = nodes[slot].next) {
|
|
pWin = (PMAINWIN)(nodes[slot].hwnd);
|
|
if (pWin && (pWin->WinType == TYPE_MAINWIN))
|
|
SendNotifyMessage ((HWND)pWin, MSG_CLOSE, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int dskDesktopCommand (HMENU hDesktopMenu, int id)
|
|
{
|
|
if (id == IDM_REDRAWBG)
|
|
SendMessage (HWND_DESKTOP, MSG_ERASEDESKTOP, 0, 0);
|
|
else if (id == IDM_CLOSEALLWIN) {
|
|
close_all_main_window ();
|
|
}
|
|
else if (id == IDM_ENDSESSION) {
|
|
#ifdef _MGHAVE_VIRTUAL_WINDOW
|
|
//close_all_main_window ();
|
|
post_quit_to_all_message_threads (TRUE);
|
|
#else
|
|
SendNotifyMessage (HWND_DESKTOP, MSG_ENDSESSION, 0, 0);
|
|
#endif /* defined _MGHAVE_VIRTUAL_WINDOW */
|
|
}
|
|
#ifdef _MGHAVE_MENU
|
|
else if (id >= IDM_FIRSTWINDOW) {
|
|
|
|
HMENU win_menu;
|
|
MENUITEMINFO mii = {MIIM_DATA};
|
|
PMAINWIN pSelectedWin;
|
|
|
|
win_menu = GetSubMenu (hDesktopMenu, 3);
|
|
if (GetMenuItemInfo (win_menu, id, MF_BYCOMMAND, &mii) == 0) {
|
|
pSelectedWin = (PMAINWIN)mii.itemdata;
|
|
|
|
if (pSelectedWin
|
|
&& pSelectedWin->WinType == TYPE_MAINWIN
|
|
&& !(pSelectedWin->dwStyle & WS_DISABLED)) {
|
|
if (sg_ptmi)
|
|
dskForceCloseMenu ();
|
|
|
|
dskMoveToTopMost (pSelectedWin, RCTM_MESSAGE, 0);
|
|
dskSetActiveWindow (pSelectedWin);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dskOnNewCtrlInstance (PCONTROL pParent, PCONTROL pNewCtrl)
|
|
{
|
|
PCONTROL pFirstCtrl, pLastCtrl;
|
|
|
|
if (pNewCtrl->dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
|
|
// Add to Z-Order list.
|
|
pNewCtrl->idx_znode = dskAllocZOrderNode ((PMAINWIN)pNewCtrl);
|
|
|
|
if (pNewCtrl->idx_znode <= 0) {
|
|
_WRN_PRINTF ("Failed to allocate znode for control.\n");
|
|
return -1;
|
|
}
|
|
|
|
// Init Global Clip Region info.
|
|
dskInitGCRInfo ((PMAINWIN)pNewCtrl);
|
|
}
|
|
|
|
pFirstCtrl = pParent->children;
|
|
|
|
pNewCtrl->next = NULL;
|
|
|
|
if (!pFirstCtrl) {
|
|
pParent->children = pNewCtrl;
|
|
pNewCtrl->prev = NULL;
|
|
}
|
|
else {
|
|
pLastCtrl = pFirstCtrl;
|
|
|
|
while (pLastCtrl->next)
|
|
pLastCtrl = pLastCtrl->next;
|
|
|
|
pLastCtrl->next = pNewCtrl;
|
|
pNewCtrl->prev = pLastCtrl;
|
|
}
|
|
|
|
dskInitInvRgn ((PMAINWIN)pNewCtrl);
|
|
|
|
pNewCtrl->pcci->nUseCount ++;
|
|
return 0;
|
|
}
|
|
|
|
static int dskOnRemoveCtrlInstance (PCONTROL pParent, PCONTROL pCtrl)
|
|
{
|
|
PCONTROL pFirstCtrl;
|
|
BOOL fFound = FALSE;
|
|
|
|
pFirstCtrl = pParent->children;
|
|
|
|
if (!pFirstCtrl)
|
|
return -1;
|
|
else {
|
|
if (pFirstCtrl == pCtrl) {
|
|
pParent->children = pCtrl->next;
|
|
if (pCtrl->next)
|
|
pCtrl->next->prev = NULL;
|
|
fFound = TRUE;
|
|
}
|
|
else {
|
|
while (pFirstCtrl->next) {
|
|
if (pFirstCtrl->next == pCtrl) {
|
|
pFirstCtrl->next = pCtrl->next;
|
|
if (pFirstCtrl->next)
|
|
pFirstCtrl->next->prev = pCtrl->prev;
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
pFirstCtrl = pFirstCtrl->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
FreeZOrderMaskRect (0, pCtrl->idx_znode);
|
|
FreeZOrderNode (0, pCtrl->idx_znode, NULL);
|
|
}
|
|
|
|
if ((HWND)pCtrl == __mg_captured_wnd) {
|
|
/* force release the capture */
|
|
__mg_captured_wnd = 0;
|
|
}
|
|
|
|
/* Since 5.0.0 */
|
|
if ((HWND)pCtrl == sg_hCaretWnd) {
|
|
sg_hCaretWnd = 0;
|
|
}
|
|
|
|
if ((HWND)pCtrl == sg_msgAutoRepeat.hwnd) {
|
|
sg_msgAutoRepeat.hwnd = 0;
|
|
}
|
|
|
|
if (fFound) {
|
|
pCtrl->pcci->nUseCount--;
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
typedef struct _REFRESH_INFO
|
|
{
|
|
const RECT* invrc;
|
|
BOOL is_empty_invrc;
|
|
} REFRESH_INFO;
|
|
|
|
static BOOL _cb_refresh_znode (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
PMAINWIN pTemp;
|
|
|
|
REFRESH_INFO* info = (REFRESH_INFO*) context;
|
|
|
|
pTemp = (PMAINWIN)node->hwnd;
|
|
|
|
if (pTemp
|
|
&& ((pTemp->WinType == TYPE_CONTROL &&
|
|
(pTemp->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
|| pTemp->WinType != TYPE_CONTROL)
|
|
&& pTemp->dwStyle & WS_VISIBLE) {
|
|
if (info->is_empty_invrc) {
|
|
SendAsyncMessage ((HWND)pTemp, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect ((HWND)pTemp, NULL, TRUE);
|
|
}
|
|
else {
|
|
RECT rcTemp, rcInv, rcWin;
|
|
|
|
if (pTemp->WinType == TYPE_CONTROL &&
|
|
(pTemp->dwExStyle & WS_EX_CTRLASMAINWIN)){
|
|
dskGetWindowRectInScreen (pTemp, &rcWin);
|
|
}
|
|
else
|
|
GetWindowRect((HWND)pTemp, &rcWin);
|
|
|
|
if (IntersectRect (&rcTemp,
|
|
&rcWin, info->invrc)) {
|
|
dskScreenToWindow (pTemp, &rcTemp, &rcInv);
|
|
SendAsyncMessage ((HWND)pTemp,
|
|
MSG_NCPAINT, 0, (LPARAM)(&rcInv));
|
|
dskScreenToClient (pTemp, &rcTemp, &rcInv);
|
|
InvalidateRect ((HWND)pTemp, &rcInv, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void dskRefreshAllWindow (const RECT* invrc)
|
|
{
|
|
REFRESH_INFO info = {invrc, FALSE};
|
|
|
|
if (invrc->top == invrc->bottom || invrc->left == invrc->right)
|
|
info.is_empty_invrc = TRUE;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
dskForceCloseMenu ();
|
|
#endif
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_ERASEDESKTOP, 0,
|
|
(LPARAM)(info.is_empty_invrc?0:&invrc));
|
|
|
|
lock_zi_for_read (__mg_zorder_info);
|
|
do_for_all_znodes (&info, __mg_zorder_info, _cb_refresh_znode, ZT_ALL);
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
}
|
|
|
|
static int dskRegisterIMEWnd (HWND hwnd)
|
|
{
|
|
if (__mg_ime_wnd != 0)
|
|
return ERR_IME_TOOMUCHIMEWND;
|
|
|
|
if (!checkAndGetMainWinIfMainWin (hwnd))
|
|
return ERR_INV_HWND;
|
|
|
|
__mg_ime_wnd = hwnd;
|
|
|
|
SendNotifyMessage (__mg_ime_wnd, MSG_IME_CLOSE, 0, 0);
|
|
|
|
#ifndef _MGRM_PROCESSES
|
|
hwnd = (HWND)dskGetActiveWindow();
|
|
if (__mg_ime_wnd != hwnd)
|
|
SendNotifyMessage (__mg_ime_wnd, MSG_IME_SETTARGET, (WPARAM)hwnd, 0);
|
|
#endif
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static int dskUnregisterIMEWnd (HWND hwnd)
|
|
{
|
|
if (__mg_ime_wnd != hwnd)
|
|
return ERR_IME_NOSUCHIMEWND;
|
|
|
|
__mg_ime_wnd = 0;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
void GUIAPI DesktopUpdateAllWindow(void)
|
|
{
|
|
SendMessage(HWND_DESKTOP, MSG_PAINT, 0, 0);
|
|
}
|
|
|
|
static void dskOnTimeout (void)
|
|
{
|
|
static DWORD uCounter = 0;
|
|
static DWORD blink_counter = 0;
|
|
|
|
if (sg_msgAutoRepeat.hwnd != 0 &&
|
|
__mg_tick_counter >= sg_msgAutoRepeat.time) {
|
|
PostMessage (sg_msgAutoRepeat.hwnd, sg_msgAutoRepeat.message,
|
|
sg_msgAutoRepeat.wParam, sg_msgAutoRepeat.lParam);
|
|
/* next auto-repeat msg after 50ms */
|
|
sg_msgAutoRepeat.time = __mg_tick_counter + (__mg_repeat_usec/10000);
|
|
}
|
|
|
|
if (__mg_tick_counter < (blink_counter + 10))
|
|
return;
|
|
|
|
uCounter += (__mg_tick_counter - blink_counter) * 10;
|
|
blink_counter = __mg_tick_counter;
|
|
|
|
if (sg_hCaretWnd != 0 &&
|
|
checkAndGetMainWinIfWindow (sg_hCaretWnd) ==
|
|
dskGetActiveWindow() &&
|
|
uCounter >= sg_uCaretBTime) {
|
|
PostMessage (sg_hCaretWnd, MSG_CARETBLINK, 0, 0);
|
|
uCounter = 0;
|
|
}
|
|
}
|
|
|
|
static LRESULT DesktopWinProc (HWND hWnd, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static HDC hDesktopDC;
|
|
WPARAM flags;
|
|
int x, y;
|
|
PMAINWIN active_mainwnd = dskGetActiveWindow();
|
|
|
|
if (message >= MSG_FIRSTWINDOWMSG && message <= MSG_LASTWINDOWMSG)
|
|
return WindowMessageHandler (message, (PMAINWIN)wParam, lParam);
|
|
|
|
if (message == MSG_CHAR && active_mainwnd) {
|
|
PostMessage ((HWND)active_mainwnd, message, wParam, lParam);
|
|
}
|
|
// VW: Since 4.0.0 for extra input messages.
|
|
else if (message >= MSG_FIRSTEXTRAINPUTMSG &&
|
|
message <= MSG_LASTEXTRAINPUTMSG) {
|
|
|
|
if (dskPreExtraMessageHandler (message, wParam, lParam))
|
|
return 0;
|
|
|
|
if (do_drag_drop_window (message, 0, 0))
|
|
return 0;
|
|
|
|
PostMessage ((HWND)active_mainwnd, message, wParam, lParam);
|
|
}
|
|
else if (message >= MSG_FIRSTKEYMSG && message <= MSG_LASTKEYMSG) {
|
|
|
|
if (dskPreKeyMessageHandler (message, wParam, lParam))
|
|
return 0;
|
|
|
|
if (do_drag_drop_window (message, 0, 0))
|
|
return 0;
|
|
|
|
if (wParam == SCANCODE_PRINTSCREEN && message == MSG_KEYDOWN) {
|
|
#ifdef _MGMISC_SAVESCREEN
|
|
static int n = 1;
|
|
char buffer[64]; // VM: 20 is too small for file name
|
|
|
|
sprintf (buffer, "%p-%d.bmp", (lParam & KS_CTRL)?
|
|
(HWND)active_mainwnd:
|
|
0, n);
|
|
if (SaveMainWindowContent ((lParam & KS_CTRL)?
|
|
(HWND)active_mainwnd:
|
|
HWND_DESKTOP,
|
|
buffer)) {
|
|
Ping ();
|
|
n ++;
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef _MGHAVE_MENU
|
|
else if (wParam == SCANCODE_ESCAPE && lParam & KS_CTRL) {
|
|
dskUpdateDesktopMenu (sg_DesktopMenu);
|
|
TrackPopupMenu (sg_DesktopMenu, TPM_DEFAULT,
|
|
0, g_rcScr.bottom, HWND_DESKTOP);
|
|
}
|
|
|
|
if (sg_ptmi) {
|
|
if (PopupMenuTrackProc (sg_ptmi, message, wParam, lParam))
|
|
return KeyMessageHandler (message, (int)wParam, (DWORD)lParam);
|
|
}
|
|
else
|
|
#endif
|
|
return KeyMessageHandler (message, (int)wParam, (DWORD)lParam);
|
|
}
|
|
|
|
if (message >= MSG_FIRSTMOUSEMSG && message <= MSG_LASTMOUSEMSG) {
|
|
|
|
if (dskPreMouseMessageHandler (message, wParam, lParam))
|
|
return 0;
|
|
|
|
flags = wParam;
|
|
|
|
x = LOSWORD (lParam);
|
|
y = HISWORD (lParam);
|
|
|
|
if (do_drag_drop_window (message, x, y))
|
|
return 0;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_ptmi) {
|
|
if (PopupMenuTrackProc (sg_ptmi, message, x, y))
|
|
return MouseMessageHandler (message, flags, x, y);
|
|
}
|
|
else
|
|
#endif
|
|
return MouseMessageHandler (message, flags, x, y);
|
|
}
|
|
|
|
if (message == MSG_COMMAND) {
|
|
|
|
if (wParam <= MAXID_RESERVED && wParam >= MINID_RESERVED) {
|
|
#ifdef _MGHAVE_MENU
|
|
dskDesktopCommand (sg_DesktopMenu, (int)wParam);
|
|
#endif
|
|
}
|
|
else {
|
|
if(dsk_ops->desktop_menucmd_handler)
|
|
dsk_ops->desktop_menucmd_handler(dt_context, (int)wParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
switch (message) {
|
|
case MSG_STARTSESSION:
|
|
__mg_init_local_sys_text ();
|
|
hDesktopDC = GetDC (HWND_DESKTOP);
|
|
|
|
dsk_ops = &def_dsk_ops;
|
|
if (dsk_ops->init)
|
|
dt_context = dsk_ops->init (hDesktopDC);
|
|
#ifdef _MGHAVE_MENU
|
|
sg_DesktopMenu = dskCreateDesktopMenu ();
|
|
#endif
|
|
break;
|
|
|
|
case MSG_REINITSESSION:
|
|
if (wParam)
|
|
__mg_init_local_sys_text ();
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_DesktopMenu) {
|
|
DestroyMenu (sg_DesktopMenu);
|
|
sg_DesktopMenu = 0;
|
|
}
|
|
|
|
sg_DesktopMenu = dskCreateDesktopMenu ();
|
|
#endif
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_ERASEDESKTOP, 0, 0);
|
|
break;
|
|
|
|
case MSG_REINITDESKOPS:
|
|
if (dsk_ops->init) {
|
|
dt_context = dsk_ops->init (hDesktopDC);
|
|
SendMessage (HWND_DESKTOP, MSG_ERASEDESKTOP, 0, 0);
|
|
}
|
|
break;
|
|
|
|
case MSG_ENDSESSION:
|
|
__mg_screensaver_destroy ();
|
|
|
|
if (hDesktopDC)
|
|
ReleaseDC (hDesktopDC);
|
|
hDesktopDC = 0;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (sg_DesktopMenu) {
|
|
DestroyMenu (sg_DesktopMenu);
|
|
sg_DesktopMenu = 0;
|
|
}
|
|
#endif
|
|
if (dsk_ops->deinit)
|
|
dsk_ops->deinit (dt_context);
|
|
|
|
PostQuitMessage (HWND_DESKTOP);
|
|
return 1;
|
|
|
|
case MSG_ERASEDESKTOP:
|
|
if (dsk_ops->paint_desktop)
|
|
dsk_ops->paint_desktop(dt_context, hDesktopDC, (PRECT)lParam);
|
|
break;
|
|
|
|
#ifndef _MGRM_THREADS
|
|
case MSG_SETFOCUS: {
|
|
HWND active_win = (HWND)dskGetActiveWindow();
|
|
if (active_win) {
|
|
SendNotifyMessage ((HWND)active_win, MSG_SETFOCUS, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
case MSG_PAINT: {
|
|
RECT invrc;
|
|
|
|
invrc.left = LOWORD(wParam);
|
|
invrc.top = HIWORD(wParam);
|
|
invrc.right = LOWORD(lParam);
|
|
invrc.bottom = HIWORD(lParam);
|
|
|
|
dskRefreshAllWindow (&invrc);
|
|
break;
|
|
}
|
|
|
|
case MSG_BROADCASTMSG:
|
|
return dskBroadcastMessage ((PMSG)lParam);
|
|
|
|
case MSG_REGISTERWNDCLASS:
|
|
return gui_AddNewControlClass ((PWNDCLASS)lParam);
|
|
|
|
case MSG_UNREGISTERWNDCLASS:
|
|
return gui_DeleteControlClass ((const char*)lParam);
|
|
|
|
case MSG_NEWCTRLINSTANCE:
|
|
return dskOnNewCtrlInstance ((PCONTROL)wParam, (PCONTROL)lParam);
|
|
|
|
case MSG_REMOVECTRLINSTANCE:
|
|
return dskOnRemoveCtrlInstance ((PCONTROL)wParam, (PCONTROL)lParam);
|
|
|
|
case MSG_GETCTRLCLASSINFO:
|
|
return (LRESULT)gui_GetControlClassInfo ((const char*)lParam);
|
|
|
|
case MSG_CTRLCLASSDATAOP:
|
|
return (LRESULT)gui_ControlClassDataOp (wParam, (WNDCLASS*)lParam);
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_REGISTERHOOKFUNC:
|
|
return (LRESULT)dskRegisterHookFunc ((int)wParam, (HOOKINFO*)lParam);
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_REGISTERHOOKWIN:
|
|
return (LRESULT)dskRegisterHookWin (0, (HWND)wParam, (DWORD)lParam);
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_UNREGISTERHOOKWIN:
|
|
return (LRESULT)dskUnregisterHookWin (0, (HWND)wParam);
|
|
|
|
#ifdef _MGHAVE_VIRTUAL_WINDOW
|
|
/* Since 5.0.0 */
|
|
case MSG_MANAGE_MSGTHREAD:
|
|
if (wParam == MSGTHREAD_SIGNIN)
|
|
return dskRegisterMsgQueue ((MSGQUEUE*)lParam);
|
|
return dskUnregisterMsgQueue ((MSGQUEUE*)lParam);
|
|
#endif
|
|
|
|
/* Since 5.0.0 */
|
|
case MSG_CALC_POSITION:
|
|
dskCalculateDefaultPosition (0, (CALCPOSINFO*)lParam);
|
|
return 0;
|
|
|
|
case MSG_IME_REGISTER:
|
|
return dskRegisterIMEWnd ((HWND)wParam);
|
|
|
|
case MSG_IME_UNREGISTER:
|
|
return dskUnregisterIMEWnd ((HWND)wParam);
|
|
|
|
case MSG_IME_SETSTATUS:
|
|
return dskSetIMEStatus ((int)wParam, (int)lParam);
|
|
|
|
case MSG_IME_SET_TARGET_INFO:
|
|
return dskSetIMETargetInfo ((IME_TARGET_INFO*)lParam);
|
|
|
|
case MSG_IME_GET_TARGET_INFO:
|
|
return dskGetIMETargetInfo ((IME_TARGET_INFO*)lParam);
|
|
|
|
case MSG_IME_GETSTATUS:
|
|
return dskGetIMEStatus ((int)wParam);
|
|
|
|
#if 0
|
|
case MSG_SRVNOTIFY:
|
|
BroadcastMessage (MSG_SRVNOTIFY, wParam, lParam);
|
|
break;
|
|
#endif
|
|
|
|
/* Since 5.0.6, the desktop handles caret blinking in MSG_TIMEOUT
|
|
message, and the interval for this message changes to about 0.05s. */
|
|
case MSG_TIMEOUT:
|
|
dskOnTimeout ();
|
|
// Since 5.0.0: MSG_IDLE messages will be generated by PeekMessage.
|
|
// BroadcastMessageInThisThread (MSG_IDLE, wParam, 0);
|
|
break;
|
|
|
|
case MSG_DT_KEYLONGPRESS:
|
|
case MSG_DT_KEYALWAYSPRESS:
|
|
case MSG_DT_KEYDOWN:
|
|
case MSG_DT_CHAR:
|
|
case MSG_DT_KEYUP:
|
|
case MSG_DT_SYSKEYDOWN:
|
|
case MSG_DT_SYSCHAR:
|
|
case MSG_DT_SYSKEYUP:
|
|
if(dsk_ops->keyboard_handler)
|
|
dsk_ops->keyboard_handler(dt_context, message, wParam, lParam);
|
|
break;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
case MSG_DT_RBUTTONUP:
|
|
dskUpdateDesktopMenu (sg_DesktopMenu);
|
|
#endif
|
|
case MSG_DT_LBUTTONDOWN:
|
|
case MSG_DT_LBUTTONUP:
|
|
case MSG_DT_LBUTTONDBLCLK:
|
|
case MSG_DT_MOUSEMOVE:
|
|
case MSG_DT_RBUTTONDOWN:
|
|
case MSG_DT_RBUTTONDBLCLK:
|
|
case MSG_DT_MBUTTONDOWN:
|
|
case MSG_DT_MBUTTONDBLCLK:
|
|
case MSG_DT_MBUTTONUP:
|
|
if(dsk_ops->mouse_handler)
|
|
dsk_ops->mouse_handler(dt_context, message, wParam, lParam);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* defined(_MGRM_THREADS) || defined(_MGRM_STANDALONE) */
|
|
|