mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-07 19:37:00 +08:00
4607 lines
129 KiB
C
4607 lines
129 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.c: The Desktop module.
|
|
**
|
|
** Current maintainer: Wei Yongming
|
|
**
|
|
*/
|
|
|
|
#include "license.h"
|
|
#ifdef _MG_ENABLE_LICENSE
|
|
# include "../sysres/license/c_files/00_minigui.dat.c"
|
|
#endif
|
|
|
|
ZORDERINFO* __mg_zorder_info;
|
|
|
|
/* pointer to desktop window */
|
|
PMAINWIN __mg_dsk_win;
|
|
|
|
/* handle to desktop window */
|
|
HWND __mg_hwnd_desktop;
|
|
|
|
/* the capture window */
|
|
HWND __mg_capture_wnd;
|
|
|
|
/* handle to the ime window - server only. */
|
|
HWND __mg_ime_wnd;
|
|
|
|
IME_STATUS_INFO __mg_ime_status_info;
|
|
|
|
static HWND sg_hCaretWnd;
|
|
static UINT sg_uCaretBTime;
|
|
/*default window procedure*/
|
|
WNDPROC __mg_def_proc[3];
|
|
|
|
static BLOCKHEAP sg_FreeInvRectList;
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
static BLOCKHEAP sg_FreeClipRectList;
|
|
static GCRINFO sg_ScrGCRInfo;
|
|
static CLIPRGN sg_UpdateRgn;
|
|
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#define DO_COMPSOR_OP(op) \
|
|
do { \
|
|
CompositorCtxt* ctxt; \
|
|
const CompositorOps* ops = ServerSelectCompositor (NULL, &ctxt); \
|
|
if (ops && ops->op) { \
|
|
ops->op(ctxt); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DO_COMPSOR_OP_ARGS(op, ...) \
|
|
do { \
|
|
CompositorCtxt* ctxt; \
|
|
const CompositorOps* ops = ServerSelectCompositor (NULL, &ctxt); \
|
|
if (ops && ops->op) { \
|
|
ops->op(ctxt, __VA_ARGS__); \
|
|
} \
|
|
} while (0)
|
|
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#define ZT_SCREENLOCK 0x00000010
|
|
#define ZT_DOCKER 0x00000020
|
|
#define ZT_GLOBAL 0x00000001
|
|
#define ZT_TOPMOST 0x00000002
|
|
#define ZT_NORMAL 0x00000004
|
|
#define ZT_LAUNCHER 0x00000040
|
|
#define ZT_ALL 0x000000FF
|
|
|
|
typedef BOOL (* CB_ONE_ZNODE) (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node);
|
|
|
|
typedef struct _DEF_CONTEXT
|
|
{
|
|
PBITMAP bg;
|
|
int x, y;
|
|
} DEF_CONTEXT;
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
PGCRINFO kernel_GetGCRgnInfo (HWND hWnd)
|
|
{
|
|
return ((PMAINWIN)hWnd)->pGCRInfo;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#if defined(_MGRM_PROCESSES)
|
|
static DEF_CONTEXT g_def_context;
|
|
#endif
|
|
|
|
static ZORDERINFO* get_zorder_info (int cli)
|
|
{
|
|
#if defined (_MGRM_THREADS) || defined (_MGRM_STANDALONE)
|
|
return __mg_zorder_info;
|
|
#else
|
|
return get_zi_from_client (cli);
|
|
#endif
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
static BOOL subtract_rgn_by_node (PCLIPRGN region, const ZORDERINFO* zi,
|
|
const ZORDERNODE* node)
|
|
{
|
|
if (node->idx_mask_rect != 0) {
|
|
MASKRECT *firstmaskrect=NULL, *maskrect;
|
|
int idx, x, y;
|
|
RECT tmprc={0};
|
|
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
idx = node->idx_mask_rect;
|
|
/* clip all mask rect */
|
|
while(idx) {
|
|
maskrect = firstmaskrect + idx;
|
|
x = maskrect->left;
|
|
y = maskrect->top;
|
|
|
|
/* convert to screen coordinate*/
|
|
x = x + node->rc.left;
|
|
y = y + node->rc.top;
|
|
|
|
SetRect(&tmprc, x, y,
|
|
x+maskrect->right - maskrect->left,
|
|
y+maskrect->bottom - maskrect->top);
|
|
|
|
IntersectRect(&tmprc, &tmprc, &(node->rc));
|
|
|
|
SubtractClipRect(region, &tmprc);
|
|
|
|
idx = maskrect->next;
|
|
}
|
|
}
|
|
else
|
|
SubtractClipRect(region, &(node->rc));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
static int get_znode_mask_bound (int cli, int idx_znode, RECT* rc_bound)
|
|
{
|
|
ZORDERINFO* zi;
|
|
ZORDERNODE* nodes, *node;
|
|
|
|
zi = get_zorder_info (cli);
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
node = nodes + idx_znode;
|
|
if (node->idx_mask_rect != 0) {
|
|
MASKRECT *firstmaskrect = NULL, *maskrect;
|
|
int idx;
|
|
RECT rc;
|
|
|
|
SetRect (rc_bound, 0, 0, 0, 0);
|
|
|
|
firstmaskrect = GET_MASKRECT (zi);
|
|
idx = node->idx_mask_rect;
|
|
while (idx) {
|
|
maskrect = firstmaskrect + idx;
|
|
rc.left = maskrect->left + node->rc.left;
|
|
rc.top = maskrect->top + node->rc.top;
|
|
rc.right = rc.left + (maskrect->right - maskrect->left);
|
|
rc.bottom = rc.top + (maskrect->bottom - maskrect->top);
|
|
|
|
IntersectRect (&rc, &rc, &(node->rc));
|
|
UnionRect (rc_bound, rc_bound, &rc);
|
|
|
|
idx = maskrect->next;
|
|
}
|
|
}
|
|
else
|
|
*rc_bound = node->rc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
static int pt_in_maskrect (const ZORDERINFO* zi,
|
|
const ZORDERNODE* nodes, int x, int y)
|
|
{
|
|
int cx, cy;
|
|
RECT tmprc;
|
|
MASKRECT *maskrect, *firstmaskrect;
|
|
int idx = nodes->idx_mask_rect;
|
|
|
|
if (idx != 0 && PtInRect (&(nodes->rc), x, y)) {
|
|
cx = x - nodes->rc.left;
|
|
cy = y - nodes->rc.top;
|
|
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
while(idx != 0) {
|
|
maskrect = firstmaskrect + idx;
|
|
SetRect (&tmprc, maskrect->left, maskrect->top,
|
|
maskrect->right, maskrect->bottom);
|
|
|
|
if (PtInRect (&tmprc, cx, cy))
|
|
return TRUE;
|
|
|
|
idx = maskrect->next;
|
|
}
|
|
return FALSE;
|
|
}
|
|
else {
|
|
return PtInRect(&(nodes->rc), x, y);
|
|
}
|
|
}
|
|
|
|
static int get_znode_at_point (const ZORDERINFO* zi,
|
|
const ZORDERNODE* nodes, int x, int y)
|
|
{
|
|
int slot;
|
|
|
|
/* Since 4.2.0 */
|
|
slot = ZNIDX_SCREENLOCK;
|
|
if (nodes[slot].hwnd && (nodes[slot].flags & ZOF_VISIBLE) &&
|
|
pt_in_maskrect (zi, &nodes[slot], x, y)) {
|
|
goto ret;
|
|
}
|
|
|
|
/* Since 4.2.0 */
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes[slot].hwnd && (nodes[slot].flags & ZOF_VISIBLE) &&
|
|
pt_in_maskrect (zi, &nodes[slot], x, y)) {
|
|
goto ret;
|
|
}
|
|
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes[slot].flags & ZOF_VISIBLE &&
|
|
pt_in_maskrect (zi, &nodes[slot], x, y))
|
|
goto ret;
|
|
}
|
|
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
pt_in_maskrect(zi, &nodes[slot], x, y))
|
|
goto ret;
|
|
}
|
|
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
pt_in_maskrect(zi, &nodes[slot], x, y)) {
|
|
goto ret;
|
|
}
|
|
}
|
|
|
|
/* Since 4.2.0 */
|
|
slot = ZNIDX_LAUNCHER;
|
|
if (nodes[slot].hwnd && (nodes[slot].flags & ZOF_VISIBLE) &&
|
|
pt_in_maskrect (zi, &nodes[slot], x, y)) {
|
|
goto ret;
|
|
}
|
|
|
|
ret:
|
|
return slot;
|
|
}
|
|
|
|
static void unchain_znode (unsigned char* usage_bmp,
|
|
ZORDERNODE* nodes, int idx_znode)
|
|
{
|
|
/* Since 4.2.0: do not call unchain_znode for fixed znodes */
|
|
assert (idx_znode != ZNIDX_SCREENLOCK ||
|
|
idx_znode != ZNIDX_DOCKER ||
|
|
idx_znode != ZNIDX_LAUNCHER);
|
|
|
|
if (nodes [idx_znode].prev) {
|
|
nodes [nodes [idx_znode].prev].next = nodes [idx_znode].next;
|
|
}
|
|
if (nodes [idx_znode].next) {
|
|
nodes [nodes [idx_znode].next].prev = nodes [idx_znode].prev;
|
|
}
|
|
|
|
__mg_slot_clear_use (usage_bmp, idx_znode);
|
|
nodes [idx_znode].flags = 0;
|
|
}
|
|
|
|
static void clean_znode_maskrect (ZORDERINFO* zi, ZORDERNODE* nodes,
|
|
int idx_znode)
|
|
{
|
|
int idx, tmp;
|
|
MASKRECT *first;
|
|
|
|
first = GET_MASKRECT(zi);
|
|
idx = nodes [idx_znode].idx_mask_rect;
|
|
|
|
while (idx) {
|
|
__mg_slot_clear_use((unsigned char*)GET_MASKRECT_USAGEBMP(zi), idx);
|
|
(first+idx)->prev = 0;
|
|
tmp = (first+idx)->next;
|
|
(first+idx)->next = 0;
|
|
idx = tmp;
|
|
}
|
|
|
|
nodes[idx_znode].idx_mask_rect = 0;
|
|
}
|
|
|
|
static int do_for_all_znodes (void* context, const ZORDERINFO* zi,
|
|
CB_ONE_ZNODE cb, DWORD types)
|
|
{
|
|
int slot;
|
|
int count = 0;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(zi);
|
|
|
|
if (types & ZT_SCREENLOCK) {
|
|
slot = ZNIDX_SCREENLOCK;
|
|
if (nodes [slot].hwnd) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
if (types & ZT_DOCKER) {
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes [slot].hwnd) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
if (types & ZT_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
if (types & ZT_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
if (types & ZT_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
if (types & ZT_LAUNCHER) {
|
|
slot = ZNIDX_LAUNCHER;
|
|
if (nodes [slot].hwnd) {
|
|
if (cb (context, zi, nodes + slot))
|
|
count ++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static void dskScreenToClient (PMAINWIN pWin,
|
|
const RECT* rcScreen, RECT* rcClient)
|
|
{
|
|
PCONTROL pParent;
|
|
|
|
rcClient->top = rcScreen->top - pWin->ct;
|
|
rcClient->left = rcScreen->left - pWin->cl;
|
|
rcClient->right = rcScreen->right - pWin->cl;
|
|
rcClient->bottom = rcScreen->bottom - pWin->ct;
|
|
|
|
pParent = (PCONTROL) pWin;
|
|
while ((pParent = pParent->pParent)) {
|
|
rcClient->top -= pParent->ct;
|
|
rcClient->left -= pParent->cl;
|
|
rcClient->right -= pParent->cl;
|
|
rcClient->bottom -= pParent->ct;
|
|
}
|
|
}
|
|
|
|
static void dskScreenToWindow (PMAINWIN pWin,
|
|
const RECT* rcScreen, RECT* rcWindow)
|
|
{
|
|
PCONTROL pParent;
|
|
|
|
rcWindow->top = rcScreen->top - pWin->top;
|
|
rcWindow->left = rcScreen->left - pWin->left;
|
|
rcWindow->right = rcScreen->right - pWin->left;
|
|
rcWindow->bottom = rcScreen->bottom - pWin->top;
|
|
|
|
pParent = (PCONTROL) pWin;
|
|
while ((pParent = pParent->pParent)) {
|
|
rcWindow->top -= pParent->ct;
|
|
rcWindow->left -= pParent->cl;
|
|
rcWindow->right -= pParent->cl;
|
|
rcWindow->bottom -= pParent->ct;
|
|
}
|
|
}
|
|
|
|
static void dskClientToScreen (PMAINWIN pWin,
|
|
const RECT* rcClient, RECT* rcScreen)
|
|
{
|
|
PCONTROL pParent;
|
|
|
|
rcScreen->top = rcClient->top + pWin->ct;
|
|
rcScreen->left = rcClient->left + pWin->cl;
|
|
rcScreen->right = rcClient->right + pWin->cl;
|
|
rcScreen->bottom = rcClient->bottom + pWin->ct;
|
|
|
|
pParent = (PCONTROL) pWin;
|
|
while ((pParent = pParent->pParent)) {
|
|
rcScreen->top += pParent->ct;
|
|
rcScreen->left += pParent->cl;
|
|
rcScreen->right += pParent->cl;
|
|
rcScreen->bottom += pParent->ct;
|
|
}
|
|
}
|
|
|
|
static void dskGetWindowRectInScreen (PMAINWIN pWin, RECT* prc)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
pParent = pCtrl = (PCONTROL)pWin;
|
|
|
|
prc->left = pCtrl->left;
|
|
prc->top = pCtrl->top;
|
|
prc->right = pCtrl->right;
|
|
prc->bottom = pCtrl->bottom;
|
|
while ((pParent = pParent->pParent)) {
|
|
prc->left += pParent->cl;
|
|
prc->top += pParent->ct;
|
|
prc->right += pParent->cl;
|
|
prc->bottom += pParent->ct;
|
|
}
|
|
}
|
|
|
|
void __mg_update_window (HWND hwnd,
|
|
int left, int top, int right, int bottom)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hwnd;
|
|
|
|
if (pWin
|
|
&& ((pWin->WinType == TYPE_CONTROL && (pWin->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
|| pWin->WinType != TYPE_CONTROL)
|
|
&& pWin->dwStyle & WS_VISIBLE) {
|
|
RECT invrc;
|
|
SetRect(&invrc, left, top, right, bottom);
|
|
|
|
if (IsRectEmpty (&invrc)) {
|
|
SendAsyncMessage ((HWND)pWin, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect ((HWND)pWin, NULL, TRUE);
|
|
}
|
|
else {
|
|
RECT rcTemp, rcInv, rcWin;
|
|
|
|
if (pWin->WinType == TYPE_CONTROL && (pWin->dwExStyle & WS_EX_CTRLASMAINWIN)){
|
|
dskGetWindowRectInScreen (pWin, &rcWin);
|
|
}
|
|
else
|
|
GetWindowRect(hwnd, &rcWin);
|
|
|
|
if (IntersectRect (&rcTemp,
|
|
&rcWin, &invrc)) {
|
|
dskScreenToWindow (pWin, &rcTemp, &rcInv);
|
|
SendAsyncMessage ((HWND)pWin,
|
|
MSG_NCPAINT, 0, (LPARAM)(&rcInv));
|
|
dskScreenToClient (pWin, &rcTemp, &rcInv);
|
|
InvalidateRect ((HWND)pWin, &rcInv, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
static int update_client_window (ZORDERNODE* znode, const RECT* rc)
|
|
{
|
|
#if defined(_MGRM_PROCESSES)
|
|
if (!mgIsServer)
|
|
return -1;
|
|
|
|
if (znode->cli != 0) {
|
|
if (rc) {
|
|
|
|
if (IsRectEmpty (&znode->dirty_rc)) {
|
|
SetRect (&znode->dirty_rc,
|
|
rc->left, rc->top, rc->right, rc->bottom);
|
|
}
|
|
else {
|
|
GetBoundRect (&znode->dirty_rc, &znode->dirty_rc, rc);
|
|
}
|
|
}
|
|
mgClients [znode->cli].has_dirty = TRUE;
|
|
}
|
|
else
|
|
#endif /* defined _MGRM_PROCESSES */
|
|
{
|
|
if (rc)
|
|
__mg_update_window (znode->hwnd, rc->left, rc->top,
|
|
rc->right, rc->bottom);
|
|
else
|
|
__mg_update_window (znode->hwnd, 0, 0, 0, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static BOOL _cb_update_znode (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* znode)
|
|
{
|
|
const RECT* rc = (RECT*)context;
|
|
|
|
if (znode->flags & ZOF_VISIBLE && znode->flags & ZOF_IF_REFERENCE) {
|
|
update_client_window (znode, rc);
|
|
znode->flags &= ~ZOF_IF_REFERENCE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL _cb_intersect_rc (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
RECT* rc = (RECT*)context;
|
|
|
|
if (node->flags & ZOF_VISIBLE && DoesIntersect (rc, &node->rc)) {
|
|
node->age++;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL _cb_update_rc (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
CLIPRGN* cliprgn = (CLIPRGN*)context;
|
|
|
|
if (node->flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(cliprgn, zi, node)) {
|
|
node->age++;
|
|
node->flags |= ZOF_IF_REFERENCE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL _cb_exclude_rc (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
if (!(node->flags & ZOF_VISIBLE))
|
|
return FALSE;
|
|
|
|
if (node->idx_mask_rect != 0) {
|
|
int idx = node->idx_mask_rect;
|
|
MASKRECT *first = GET_MASKRECT(zi);
|
|
int x, y;
|
|
RECT rc;
|
|
|
|
while (idx != 0) {
|
|
x = node->rc.left + (first+idx)->left;
|
|
y = node->rc.top + (first+idx)->top;
|
|
SetRect(&rc, x, y,
|
|
x+(first+idx)->right-(first+idx)->left,
|
|
y+(first+idx)->bottom-(first+idx)->top);
|
|
ExcludeClipRect (HDC_SCREEN_SYS, &rc);
|
|
idx = (first+idx)->next;
|
|
}
|
|
}
|
|
else
|
|
ExcludeClipRect (HDC_SCREEN_SYS, &node->rc);
|
|
|
|
return TRUE;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
static inline void reset_window (PMAINWIN pWin, RECT* rcWin) { }
|
|
#else
|
|
static void reset_window (PMAINWIN pWin, RECT* rcWin)
|
|
{
|
|
PGCRINFO pGCRInfo;
|
|
RECT rcScr, rcTemp;
|
|
|
|
pGCRInfo = pWin->pGCRInfo;
|
|
rcScr = GetScreenRect();
|
|
IntersectRect (&rcTemp, rcWin, &rcScr);
|
|
SetClipRgn (&pGCRInfo->crgn, &rcTemp);
|
|
}
|
|
#endif
|
|
|
|
#ifdef _MGRM_THREADS
|
|
#ifndef __NOUNIX__
|
|
/*for unix system, using read/write lock*/
|
|
static inline void lock_zi_for_change (const ZORDERINFO* zi)
|
|
{
|
|
pthread_rwlock_wrlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void unlock_zi_for_change (const ZORDERINFO* zi)
|
|
{
|
|
pthread_rwlock_unlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void lock_zi_for_read (const ZORDERINFO* zi)
|
|
{
|
|
pthread_rwlock_rdlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void unlock_zi_for_read (const ZORDERINFO* zi)
|
|
{
|
|
pthread_rwlock_unlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
#else /* __NOUNIX__ */
|
|
/*for non-unix system, using mutex*/
|
|
static inline void lock_zi_for_change (const ZORDERINFO* zi)
|
|
{
|
|
pthread_mutex_lock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void unlock_zi_for_change (const ZORDERINFO* zi)
|
|
{
|
|
pthread_mutex_unlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void lock_zi_for_read (const ZORDERINFO* zi)
|
|
{
|
|
pthread_mutex_lock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
|
|
static inline void unlock_zi_for_read (const ZORDERINFO* zi)
|
|
{
|
|
pthread_mutex_unlock(&((ZORDERINFO*)zi)->rwlock);
|
|
}
|
|
#endif /* __NOUNIX__ */
|
|
|
|
#elif defined(_MGRM_STANDALONE)
|
|
static inline void lock_zi_for_change (const ZORDERINFO* zi) { }
|
|
static inline void unlock_zi_for_change (const ZORDERINFO* zi) { }
|
|
static inline void lock_zi_for_read (const ZORDERINFO* zi) { }
|
|
static inline void unlock_zi_for_read (const ZORDERINFO* zi) { }
|
|
#else /* for procs */
|
|
/* NULL. see desktop-procs.c */
|
|
#endif /* _MGRM_THREADS */
|
|
|
|
static int RestrictControlRect(PMAINWIN pWin, RECT *minimal)
|
|
{
|
|
RECT rcMove;
|
|
int off_x = 0, off_y = 0;
|
|
|
|
PCONTROL pCtrl = gui_Control((HWND)pWin);
|
|
PCONTROL pRoot = (PCONTROL)(pWin->pMainWin);
|
|
|
|
if (pCtrl == NULL)
|
|
return FALSE;
|
|
|
|
do {
|
|
PCONTROL pParent = pCtrl;
|
|
|
|
rcMove.left = pRoot->cl + off_x;
|
|
rcMove.top = pRoot->ct + off_y;
|
|
rcMove.right = pRoot->cr + off_x;
|
|
rcMove.bottom = pRoot->cb + off_y;
|
|
|
|
dskScreenToClient (pWin, &rcMove, &rcMove);
|
|
|
|
if (!IntersectRect (minimal, minimal, &rcMove)) {
|
|
SetRect (minimal, 0, 0, 0, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
off_x += pRoot->cl;
|
|
off_y += pRoot->ct;
|
|
|
|
if (pRoot == pCtrl->pParent)
|
|
break;
|
|
|
|
while (TRUE) {
|
|
if (pRoot->children == pParent->pParent->children) {
|
|
pRoot = pParent;
|
|
break;
|
|
}
|
|
pParent = pParent->pParent;
|
|
}
|
|
} while (TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int dskScrollMainWindow (PMAINWIN pWin, PSCROLLWINDOWINFO pswi)
|
|
{
|
|
HDC hdc;
|
|
RECT rcClient, rcScreen, rcInvalid;
|
|
BOOL inved = FALSE;
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
CLIPRECT crcOne;
|
|
#endif
|
|
PCLIPRECT pcrc;
|
|
PINVRGN pInvRgn;
|
|
PCLIPRGN prgn = NULL;
|
|
|
|
dskClientToScreen (pWin, pswi->rc1, &rcScreen);
|
|
|
|
//BUGFIX: if the MainWindow is AutoSecondaryDC, the secondaryDC and
|
|
//client dc would be diffirent, so we must get the scondaryDC,
|
|
//the update to client dc (dongjunjie 2010/7/28)
|
|
//hdc = GetClientDC ((HWND)pWin);
|
|
hdc = get_valid_dc (pWin, TRUE);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
pcrc = kernel_GetGCRgnInfo ((HWND)pWin)->crgn.head;
|
|
#else
|
|
crcOne.next = crcOne.prev = NULL;
|
|
crcOne.rc.left = pWin->left;
|
|
crcOne.rc.top = pWin->top;
|
|
crcOne.rc.right = pWin->right;
|
|
crcOne.rc.bottom = pWin->bottom;
|
|
pcrc = &crcOne;
|
|
#endif
|
|
while (pcrc) {
|
|
RECT rcMove;
|
|
|
|
if (!IntersectRect (&rcMove, &pcrc->rc, &rcScreen)) {
|
|
pcrc = pcrc->next;
|
|
continue;
|
|
}
|
|
|
|
dskScreenToClient (pWin, &rcMove, &rcMove);
|
|
if (!IntersectRect (&rcMove, &rcMove, pswi->rc1)) {
|
|
pcrc = pcrc->next;
|
|
continue;
|
|
}
|
|
|
|
if (pWin->dwExStyle & WS_EX_TRANSPARENT) {
|
|
/* set invalidate rect. */
|
|
InvalidateRect ((HWND)pWin, &rcMove, TRUE);
|
|
inved = TRUE;
|
|
}
|
|
else {
|
|
RestrictControlRect (pWin, &rcMove);
|
|
|
|
SelectClipRect (hdc, &rcMove);
|
|
|
|
BitBlt (hdc, rcMove.left, rcMove.top,
|
|
rcMove.right - rcMove.left,
|
|
rcMove.bottom - rcMove.top,
|
|
hdc, pswi->iOffx + rcMove.left, pswi->iOffy + rcMove.top, 0);
|
|
}
|
|
|
|
pcrc = pcrc->next;
|
|
}
|
|
//ReleaseDC (hdc);
|
|
//BUGFIXED: we must update the secondaryDC to clientDC, to ensure
|
|
//the secondaryDC and clientDC are same (dongjunjie 2010/07/08)
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
HDC real_dc = GetClientDC((HWND)pWin->pMainWin);
|
|
__mg_update_secondary_dc(pWin, hdc, real_dc, pswi->rc1, HT_CLIENT);
|
|
ReleaseDC (real_dc);
|
|
}
|
|
release_valid_dc(pWin, hdc);
|
|
|
|
GetClientRect((HWND)pWin, &rcClient);
|
|
|
|
pInvRgn = &pWin->InvRgn;
|
|
if (!pInvRgn->frozen) {
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_lock (&pInvRgn->lock);
|
|
#endif
|
|
/*scroll whole screen, offset invalid region*/
|
|
if (EqualRect (pswi->rc1, &rcClient))
|
|
OffsetRegion (&(pInvRgn->rgn), pswi->iOffx, pswi->iOffy);
|
|
else
|
|
OffsetRegionEx (&(pInvRgn->rgn), &rcClient,
|
|
pswi->rc1, pswi->iOffx, pswi->iOffy);
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_unlock (&pInvRgn->lock);
|
|
#endif
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
prgn = CreateClipRgn ();
|
|
lock_zi_for_read (__mg_zorder_info);
|
|
CopyRegion (prgn, &kernel_GetGCRgnInfo((HWND)pWin)->crgn);
|
|
pcrc = prgn->head;
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
#else
|
|
pcrc = &crcOne;
|
|
#endif
|
|
|
|
while (pcrc) {
|
|
BOOL bNeedInvalidate = FALSE;
|
|
RECT rcMove;
|
|
if (!IntersectRect (&rcMove, &pcrc->rc, &rcScreen)) {
|
|
pcrc = pcrc->next;
|
|
continue;
|
|
}
|
|
|
|
dskScreenToClient (pWin, &rcMove, &rcMove);
|
|
|
|
RestrictControlRect (pWin, &rcMove);
|
|
|
|
rcInvalid = rcMove;
|
|
|
|
if (pswi->iOffx < 0) {
|
|
rcInvalid.left = rcInvalid.right + pswi->iOffx;
|
|
bNeedInvalidate = TRUE;
|
|
}
|
|
else if (pswi->iOffx > 0) {
|
|
rcInvalid.right = rcInvalid.left + pswi->iOffx;
|
|
bNeedInvalidate = TRUE;
|
|
}
|
|
|
|
/*
|
|
* BUGFIXED: offx and offy would make the two diffrent areas invalidate
|
|
* we should invalid both them (dongjunjie) 2010/07/30
|
|
*
|
|
* content
|
|
* ---------------------------
|
|
* |//: offX |
|
|
* |//: |
|
|
* |//: View |
|
|
* |//: |
|
|
* |//: |
|
|
* |/////////////////////////| offY
|
|
* ---------------------------
|
|
* // - represent area need the Need invalidate
|
|
* see the to area must be invalidate
|
|
*/
|
|
if (bNeedInvalidate) {
|
|
InvalidateRect ((HWND)pWin, &rcInvalid, TRUE);
|
|
rcInvalid = rcMove; //restore the invalidate area
|
|
bNeedInvalidate = FALSE; //resotre the inved value
|
|
inved = TRUE;
|
|
}
|
|
|
|
if (pswi->iOffy < 0) {
|
|
rcInvalid.top = rcInvalid.bottom + pswi->iOffy;
|
|
bNeedInvalidate = TRUE;
|
|
}
|
|
else if (pswi->iOffy > 0) {
|
|
rcInvalid.bottom = rcInvalid.top + pswi->iOffy;
|
|
bNeedInvalidate = TRUE;
|
|
}
|
|
|
|
if (bNeedInvalidate) {
|
|
InvalidateRect ((HWND)pWin, &rcInvalid, TRUE);
|
|
inved = TRUE;
|
|
}
|
|
|
|
pcrc = pcrc->next;
|
|
}
|
|
|
|
if (prgn)
|
|
DestroyClipRgn (prgn);
|
|
|
|
if (inved) {
|
|
PostMessage ((HWND)pWin, MSG_PAINT, 0, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
void __mg_unlock_gcrinfo (PDC pdc)
|
|
{
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_unlock (&pdc->pGCRInfo->lock);
|
|
#endif
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
return;
|
|
}
|
|
|
|
static BOOL _cb_recalc_gcrinfo (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
PGCRINFO gcrinfo;
|
|
|
|
if (!(node->flags & ZOF_VISIBLE))
|
|
return FALSE;
|
|
|
|
gcrinfo = (PGCRINFO)context;
|
|
return subtract_rgn_by_node(&gcrinfo->crgn, zi, node);
|
|
}
|
|
|
|
void __mg_lock_recalc_gcrinfo (PDC pdc)
|
|
{
|
|
PGCRINFO gcrinfo;
|
|
PMAINWIN mainwin;
|
|
ZORDERINFO* zi = __mg_zorder_info;
|
|
ZORDERNODE* menu_nodes, *nodes;
|
|
int i, slot = 0, idx_znode;
|
|
unsigned short idx;
|
|
CLIPRGN invisible_rgn;
|
|
|
|
gcrinfo = kernel_GetGCRgnInfo (pdc->hwnd);
|
|
mainwin = (PMAINWIN)(pdc->hwnd);
|
|
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_lock (&pdc->pGCRInfo->lock);
|
|
#endif
|
|
lock_zi_for_read (zi);
|
|
|
|
menu_nodes = GET_MENUNODE(zi);
|
|
nodes = menu_nodes + DEF_NR_POPUPMENUS;
|
|
idx_znode = mainwin->idx_znode;
|
|
|
|
if (gcrinfo->old_zi_age == nodes [idx_znode].age) {
|
|
return;
|
|
}
|
|
|
|
idx = nodes [idx_znode].idx_mask_rect;
|
|
reset_window (mainwin, &nodes [idx_znode].rc);
|
|
/* when idx=0, this is HDC_SCREEN_SYS */
|
|
if (idx != 0) {
|
|
InitClipRgn (&invisible_rgn, &sg_FreeClipRectList);
|
|
SetClipRgn (&invisible_rgn, &nodes [idx_znode].rc);
|
|
|
|
subtract_rgn_by_node(&invisible_rgn, zi, &nodes[idx_znode]);
|
|
SubtractRegion (&gcrinfo->crgn, &gcrinfo->crgn, &invisible_rgn);
|
|
EmptyClipRgn(&invisible_rgn);
|
|
}
|
|
|
|
/* clip by popup menus */
|
|
for (i = 0; i < zi->nr_popupmenus; i++) {
|
|
SubtractClipRect (&gcrinfo->crgn, &menu_nodes [i].rc);
|
|
}
|
|
|
|
/* Since 4.2.0: check fixed znodes */
|
|
switch (nodes[idx_znode].flags & ZOF_TYPE_MASK) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
slot = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZOF_TYPE_DOCKER:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_SCREENLOCK);
|
|
slot = ZNIDX_DOCKER;
|
|
break;
|
|
|
|
case ZOF_TYPE_GLOBAL:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_SCREENLOCK);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_DOCKER);
|
|
slot = zi->first_global;
|
|
break;
|
|
|
|
case ZOF_TYPE_TOPMOST:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_SCREENLOCK);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_DOCKER);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_GLOBAL);
|
|
slot = zi->first_topmost;
|
|
break;
|
|
|
|
case ZOF_TYPE_NORMAL:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_SCREENLOCK);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_DOCKER);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_GLOBAL);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_TOPMOST);
|
|
slot = zi->first_normal;
|
|
break;
|
|
|
|
case ZOF_TYPE_LAUNCHER:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_SCREENLOCK);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_DOCKER);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_GLOBAL);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_TOPMOST);
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_NORMAL);
|
|
slot = ZNIDX_LAUNCHER;
|
|
break;
|
|
|
|
case ZOF_TYPE_DESKTOP:
|
|
do_for_all_znodes (gcrinfo, zi,
|
|
_cb_recalc_gcrinfo, ZT_ALL);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
while (slot && slot != idx_znode) {
|
|
|
|
if (nodes [slot].flags & ZOF_VISIBLE)
|
|
subtract_rgn_by_node (&gcrinfo->crgn, zi, &nodes[slot]);
|
|
|
|
slot = nodes [slot].next;
|
|
}
|
|
gcrinfo->old_zi_age = nodes [idx_znode].age;
|
|
gcrinfo->age++;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/*
|
|
* Init a window's global clipping region.
|
|
*/
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
static inline void dskInitGCRInfo (PMAINWIN pWin) {}
|
|
#else
|
|
static void dskInitGCRInfo (PMAINWIN pWin)
|
|
{
|
|
RECT rcWin, rcScr, rcTemp;
|
|
|
|
dskGetWindowRectInScreen (pWin, &rcWin);
|
|
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_init (&pWin->pGCRInfo->lock, NULL);
|
|
#endif
|
|
pWin->pGCRInfo->age = 0;
|
|
pWin->pGCRInfo->old_zi_age = 0;
|
|
|
|
InitClipRgn (&pWin->pGCRInfo->crgn, &sg_FreeClipRectList);
|
|
rcScr = GetScreenRect();
|
|
IntersectRect (&rcTemp, &rcWin, &rcScr);
|
|
SetClipRgn (&pWin->pGCRInfo->crgn, &rcTemp);
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/*
|
|
* Init a window's invalid region.
|
|
*/
|
|
static void dskInitInvRgn (PMAINWIN pWin)
|
|
{
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_init (&pWin->InvRgn.lock, NULL);
|
|
#endif
|
|
pWin->InvRgn.frozen = 0;
|
|
InitClipRgn (&pWin->InvRgn.rgn, &sg_FreeInvRectList);
|
|
MAKE_REGION_INFINITE(&pWin->InvRgn.rgn);
|
|
}
|
|
|
|
int __kernel_get_next_znode (const ZORDERINFO* zi, int from)
|
|
{
|
|
int next = 0;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(zi);
|
|
|
|
if (from <= 0) {
|
|
if (nodes [ZNIDX_SCREENLOCK].hwnd) {
|
|
next = ZNIDX_SCREENLOCK;
|
|
}
|
|
else if (nodes [ZNIDX_DOCKER].hwnd) {
|
|
next = ZNIDX_DOCKER;
|
|
}
|
|
else {
|
|
next = zi->first_global;
|
|
if (next == 0)
|
|
next = zi->first_topmost;
|
|
if (next == 0)
|
|
next = zi->first_normal;
|
|
if (next == 0 && nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
switch (from) {
|
|
case ZNIDX_SCREENLOCK:
|
|
if (nodes [ZNIDX_DOCKER].hwnd)
|
|
next = ZNIDX_DOCKER;
|
|
if (next == 0)
|
|
next = zi->first_global;
|
|
if (next == 0)
|
|
next = zi->first_topmost;
|
|
if (next == 0)
|
|
next = zi->first_normal;
|
|
if (next == 0 && nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
if (next == 0)
|
|
return 0;
|
|
break;
|
|
|
|
case ZNIDX_DOCKER:
|
|
next = zi->first_global;
|
|
if (next == 0)
|
|
next = zi->first_topmost;
|
|
if (next == 0)
|
|
next = zi->first_normal;
|
|
if (next == 0 && nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
if (next == 0)
|
|
return 0;
|
|
break;
|
|
|
|
case ZNIDX_LAUNCHER:
|
|
return 0; /* the bottommost znode */
|
|
break;
|
|
|
|
default:
|
|
next = nodes [from].next;
|
|
break;
|
|
}
|
|
|
|
if (next > 0)
|
|
return next;
|
|
|
|
// next is still zero, from is not fixed znode.
|
|
switch (nodes [from].flags & ZOF_TYPE_MASK) {
|
|
case ZOF_TYPE_GLOBAL:
|
|
next = zi->first_topmost;
|
|
if (next == 0)
|
|
next = zi->first_normal;
|
|
if (next == 0 && nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
break;
|
|
|
|
case ZOF_TYPE_TOPMOST:
|
|
next = zi->first_normal;
|
|
if (next == 0 && nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
break;
|
|
|
|
case ZOF_TYPE_NORMAL:
|
|
if (nodes [ZNIDX_LAUNCHER].hwnd)
|
|
next = ZNIDX_LAUNCHER;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
int __kernel_get_prev_znode (const ZORDERINFO* zi, int from)
|
|
{
|
|
int prev = 0;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(zi);
|
|
|
|
if (from <= 0) {
|
|
if (nodes [ZNIDX_LAUNCHER].hwnd) {
|
|
prev = ZNIDX_LAUNCHER;
|
|
}
|
|
else {
|
|
if (zi->first_normal) {
|
|
prev = zi->first_normal;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
else if (zi->first_topmost) {
|
|
prev = zi->first_topmost;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
else if (zi->first_global) {
|
|
prev = zi->first_global;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
|
|
if (prev == 0 && nodes [ZNIDX_DOCKER].hwnd)
|
|
prev = ZNIDX_DOCKER;
|
|
if (prev == 0 && nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
}
|
|
|
|
return prev;
|
|
}
|
|
|
|
switch (from) {
|
|
case ZNIDX_LAUNCHER:
|
|
if (zi->first_normal) {
|
|
prev = zi->first_normal;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
else if (zi->first_topmost) {
|
|
prev = zi->first_topmost;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
else if (zi->first_global) {
|
|
prev = zi->first_global;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
|
|
if (prev == 0 && nodes [ZNIDX_DOCKER].hwnd)
|
|
prev = ZNIDX_DOCKER;
|
|
if (prev == 0 && nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZNIDX_DOCKER:
|
|
if (nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZNIDX_SCREENLOCK:
|
|
return 0; /* the topmost znode */
|
|
break;
|
|
|
|
default:
|
|
prev = nodes [from].prev;
|
|
break;
|
|
}
|
|
|
|
if (prev > 0)
|
|
return prev;
|
|
|
|
// prev is still zero, and from is not fixed znode.
|
|
switch (nodes [from].flags & ZOF_TYPE_MASK) {
|
|
case ZOF_TYPE_NORMAL:
|
|
if (zi->first_topmost) {
|
|
prev = zi->first_topmost;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
else if (zi->first_global) {
|
|
prev = zi->first_global;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
|
|
if (prev == 0 && nodes [ZNIDX_DOCKER].hwnd)
|
|
prev = ZNIDX_DOCKER;
|
|
if (prev == 0 && nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZOF_TYPE_TOPMOST:
|
|
if (zi->first_global) {
|
|
prev = zi->first_global;
|
|
while (nodes [prev].next) {
|
|
prev = nodes [prev].next;
|
|
}
|
|
}
|
|
|
|
if (prev == 0 && nodes [ZNIDX_DOCKER].hwnd)
|
|
prev = ZNIDX_DOCKER;
|
|
if (prev == 0 && nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZOF_TYPE_GLOBAL:
|
|
if (nodes [ZNIDX_DOCKER].hwnd)
|
|
prev = ZNIDX_DOCKER;
|
|
if (prev == 0 && nodes [ZNIDX_SCREENLOCK].hwnd)
|
|
prev = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return prev;
|
|
}
|
|
|
|
static int get_next_activable_mainwin (const ZORDERINFO* zi, int from)
|
|
{
|
|
int next;
|
|
ZORDERNODE* nodes = GET_ZORDERNODE(zi);
|
|
|
|
do {
|
|
next = __kernel_get_next_znode (zi, from);
|
|
if (next <= 0)
|
|
break;
|
|
|
|
if (nodes [next].flags & ZOF_TF_MAINWIN
|
|
&& (nodes [next].flags & ZOF_VISIBLE)
|
|
&& !(nodes [next].flags & ZOF_DISABLED))
|
|
return next;
|
|
|
|
from = next;
|
|
} while (1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Add new hosted main window.
|
|
*/
|
|
static 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;
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
/*
|
|
* Moves a window to topmost.
|
|
*
|
|
* dskIsTopMost
|
|
* dskMove2Top
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static BOOL dskIsTopMost (PMAINWIN pWin)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
lock_zi_for_read (__mg_zorder_info);
|
|
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
if (pWin->idx_znode <= ZNIDX_LAUNCHER)
|
|
ret = TRUE;
|
|
else if (__mg_zorder_info->first_global == pWin->idx_znode)
|
|
ret = TRUE;
|
|
else if (__mg_zorder_info->first_topmost == pWin->idx_znode)
|
|
ret = TRUE;
|
|
else if (__mg_zorder_info->first_normal == pWin->idx_znode)
|
|
ret = TRUE;
|
|
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
static PTRACKMENUINFO sg_ptmi;
|
|
static HMENU sg_DesktopMenu = 0; /* system global desktop menu handle */
|
|
|
|
// call back proc of tracking menu.
|
|
// defined in Menu module.
|
|
int PopupMenuTrackProc (PTRACKMENUINFO ptmi,
|
|
int message, WPARAM wParam, LPARAM lParam);
|
|
|
|
static int srvForceCloseMenu (int cli)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
int i, ret = 0;
|
|
#if defined(_MGRM_PROCESSES)
|
|
int cli_trackmenu;
|
|
#endif
|
|
ZORDERNODE* menu_nodes;
|
|
RECT rc_bound;
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
ZORDERNODE* win_nodes;
|
|
RECT rc_screen;
|
|
#endif
|
|
|
|
if (zi->cli_trackmenu < 0 || zi->nr_popupmenus == 0)
|
|
return 0;
|
|
|
|
menu_nodes = GET_MENUNODE(zi);
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
win_nodes = menu_nodes + DEF_NR_POPUPMENUS;
|
|
#endif
|
|
SetRect (&rc_bound, 0, 0, 0, 0);
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
for (i = 0; i < zi->nr_popupmenus; i++) {
|
|
GetBoundRect (&rc_bound, &rc_bound, &menu_nodes [i].rc);
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
SetClipRgn (&sg_UpdateRgn, &rc_bound);
|
|
|
|
/* check influenced window zorder nodes */
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_ALL);
|
|
|
|
rc_screen = GetScreenRect ();
|
|
if (SubtractClipRect (&sg_UpdateRgn, &rc_screen)) {
|
|
win_nodes [0].age++;
|
|
win_nodes [0].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
for (i = (zi->nr_popupmenus - 1); i >= 0; i--) {
|
|
DO_COMPSOR_OP_ARGS (on_hiding_ppp, i);
|
|
DeleteMemDC (menu_nodes[i].mem_dc);
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#if defined(_MGRM_PROCESSES)
|
|
cli_trackmenu = zi->cli_trackmenu;
|
|
#endif
|
|
zi->cli_trackmenu = -1;
|
|
zi->nr_popupmenus = 0;
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
/* update all znode if it's dirty */
|
|
do_for_all_znodes (&rc_bound, zi, _cb_update_znode, ZT_ALL);
|
|
|
|
if (win_nodes [0].flags & ZOF_IF_REFERENCE) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ERASEDESKTOP, 0, (LPARAM)&rc_bound);
|
|
win_nodes [0].flags &= ~ZOF_IF_REFERENCE;
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
DO_COMPSOR_OP_ARGS (on_closed_menu, &rc_bound);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* notify the client to close the menu */
|
|
{
|
|
#if defined(_MGRM_PROCESSES)
|
|
MSG msg = {0, MSG_CLOSEMENU, 0, 0, __mg_timer_counter};
|
|
|
|
if (cli_trackmenu)
|
|
ret = __mg_send2client (&msg, mgClients + cli_trackmenu);
|
|
else
|
|
#endif
|
|
SendMessage (HWND_DESKTOP, MSG_CLOSEMENU, 0, 0);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int srvStartTrackPopupMenu (int cli, const RECT* rc, HWND ptmi,
|
|
Uint32 surf_flags, size_t surf_size, int fd)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* menu_nodes;
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
HDC memdc = HDC_INVALID;
|
|
#else
|
|
ZORDERNODE* win_nodes;
|
|
RECT rc_screen;
|
|
#endif
|
|
|
|
if (zi->cli_trackmenu >= 0 && zi->cli_trackmenu != cli) {
|
|
srvForceCloseMenu (0);
|
|
}
|
|
|
|
if (zi->nr_popupmenus == zi->max_nr_popupmenus)
|
|
return -1;
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
{
|
|
GAL_Surface* surf;
|
|
if (cli == 0) {
|
|
surf = GetSurfaceFromDC (((PTRACKMENUINFO)ptmi)->dc);
|
|
}
|
|
else if (fd >= 0) {
|
|
surf = GAL_AttachSharedRGBSurface (fd, surf_size, surf_flags, TRUE);
|
|
close (fd);
|
|
}
|
|
else {
|
|
_ERR_PRINTF("KERNEL: not server but fd for shared surface is invalid\n");
|
|
return -1;
|
|
}
|
|
|
|
if (surf) {
|
|
memdc = CreateMemDCFromSurface (surf);
|
|
if (memdc == HDC_INVALID) {
|
|
GAL_FreeSurface (surf);
|
|
_ERR_PRINTF("KERNEL: failed to create memory dc for znode\n");
|
|
return -1;
|
|
}
|
|
}
|
|
else {
|
|
_ERR_PRINTF("KERNEL: failed to attach to surface\n");
|
|
return -1;
|
|
}
|
|
}
|
|
#endif /* def _MGSCHEMA_COMPOSITING */
|
|
|
|
menu_nodes = GET_MENUNODE(zi);
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
win_nodes = menu_nodes + DEF_NR_POPUPMENUS;
|
|
|
|
/* check influenced window zorder nodes */
|
|
do_for_all_znodes ((void*)rc, zi, _cb_intersect_rc, ZT_ALL);
|
|
|
|
rc_screen = GetScreenRect();
|
|
if (DoesIntersect (rc, &rc_screen)) {
|
|
win_nodes [0].age++;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
menu_nodes [zi->nr_popupmenus].flags = ZOF_TYPE_POPUPMENU;
|
|
menu_nodes [zi->nr_popupmenus].rc = *rc;
|
|
menu_nodes [zi->nr_popupmenus].hwnd = ptmi;
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
menu_nodes [zi->nr_popupmenus].changes = 0;
|
|
menu_nodes [zi->nr_popupmenus].ct = CT_OPAQUE;
|
|
menu_nodes [zi->nr_popupmenus].ct_arg = 0;
|
|
menu_nodes [zi->nr_popupmenus].mem_dc = memdc;
|
|
menu_nodes [zi->nr_popupmenus].dirty_rcs = NULL;
|
|
#endif
|
|
menu_nodes [zi->nr_popupmenus].priv_data = NULL;
|
|
|
|
if (zi->cli_trackmenu == -1)
|
|
zi->cli_trackmenu = cli;
|
|
zi->nr_popupmenus ++;
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
DO_COMPSOR_OP_ARGS (on_showing_ppp, zi->nr_popupmenus - 1);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return zi->nr_popupmenus - 1;
|
|
}
|
|
|
|
static int srvEndTrackPopupMenu (int cli, int idx_znode)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* menu_nodes;
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
ZORDERNODE* win_nodes;
|
|
RECT rc, rc_screen;
|
|
#endif
|
|
|
|
if (zi->cli_trackmenu != cli
|
|
|| zi->nr_popupmenus != (idx_znode + 1))
|
|
return -1;
|
|
|
|
menu_nodes = GET_MENUNODE(zi);
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
win_nodes = menu_nodes + DEF_NR_POPUPMENUS;
|
|
#endif
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
DO_COMPSOR_OP_ARGS (on_hiding_ppp, idx_znode);
|
|
DeleteMemDC (menu_nodes [idx_znode].mem_dc);
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
rc = menu_nodes [idx_znode].rc;
|
|
SetClipRgn (&sg_UpdateRgn, &rc);
|
|
|
|
/* check influenced window zorder nodes */
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_ALL);
|
|
|
|
rc_screen = GetScreenRect();
|
|
if (SubtractClipRect (&sg_UpdateRgn, &rc_screen)) {
|
|
win_nodes [0].age++;
|
|
win_nodes [0].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
zi->nr_popupmenus --;
|
|
if (zi->nr_popupmenus == 0)
|
|
zi->cli_trackmenu = -1;
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
/* update all znode if it's dirty */
|
|
do_for_all_znodes (&rc, zi, _cb_update_znode, ZT_ALL);
|
|
|
|
if (win_nodes [0].flags & ZOF_IF_REFERENCE) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ERASEDESKTOP, 0, (LPARAM)&rc);
|
|
win_nodes [0].flags &= ~ZOF_IF_REFERENCE;
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
DO_COMPSOR_OP_ARGS (on_dirty_screen, NULL,
|
|
menu_nodes [idx_znode].flags & ZOF_TYPE_FLAG_MASK,
|
|
&menu_nodes [idx_znode].rc);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static BOOL dskCloseMenu (void)
|
|
{
|
|
if (sg_ptmi == NULL)
|
|
return FALSE;
|
|
|
|
SendNotifyMessage (sg_ptmi->hwnd,
|
|
MSG_DEACTIVEMENU,
|
|
(WPARAM)sg_ptmi->pmb,
|
|
(LPARAM)sg_ptmi->pmi);
|
|
|
|
PopupMenuTrackProc (sg_ptmi, MSG_CLOSEMENU, 0, 0);
|
|
|
|
sg_ptmi = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
int __mg_post_msg_by_znode (const ZORDERINFO* zi, int znode,
|
|
int message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int ret = 0;
|
|
ZORDERNODE* nodes;
|
|
|
|
if (znode < 0)
|
|
return -1;
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
if (nodes [znode].cli == 0) {
|
|
ret = PostMessage (nodes [znode].main_win,
|
|
message, wParam, lParam);
|
|
}
|
|
#if defined (_MGRM_PROCESSES)
|
|
else {
|
|
MSG msg = {nodes [znode].main_win,
|
|
message, wParam, lParam, __mg_timer_counter};
|
|
|
|
ret = __mg_send2client (&msg, mgClients + nodes [znode].cli);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
post_msg_by_znode_p (const ZORDERINFO* zi, const ZORDERNODE* znode,
|
|
int message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (!znode->main_win) {
|
|
return 0;
|
|
}
|
|
if (znode->cli == 0) {
|
|
ret = PostMessage (znode->main_win, message, wParam, lParam);
|
|
}
|
|
#if defined (_MGRM_PROCESSES)
|
|
else {
|
|
MSG msg = {znode->main_win,
|
|
message, wParam, lParam, __mg_timer_counter};
|
|
|
|
ret = __mg_send2client (&msg, mgClients + znode->cli);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static HWND dskSetActiveZOrderNode (int cli, int idx_znode)
|
|
{
|
|
int old_active = 0;
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* nodes;
|
|
HWND old_hwnd = HWND_NULL, new_hwnd = HWND_NULL;
|
|
|
|
if (idx_znode > zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals) {
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
if ((__mg_ime_wnd && __mg_ime_wnd == nodes [idx_znode].main_win) ||
|
|
nodes [idx_znode].flags & ZOF_TF_TOOLWIN)
|
|
return HWND_INVALID;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
if (zi->active_win) {
|
|
old_active = zi->active_win;
|
|
}
|
|
|
|
zi->active_win = idx_znode;
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
if (old_active) {
|
|
if (nodes [old_active].cli == cli) {
|
|
old_hwnd = nodes [old_active].hwnd;
|
|
}
|
|
else
|
|
old_hwnd = HWND_OTHERPROC;
|
|
}
|
|
|
|
if (idx_znode) {
|
|
if (nodes [idx_znode].cli == cli) {
|
|
new_hwnd = nodes [idx_znode].hwnd;
|
|
}
|
|
else
|
|
new_hwnd = HWND_OTHERPROC;
|
|
}
|
|
|
|
if (old_active && (nodes [zi->active_win].flags & ZOF_VISIBLE)) {
|
|
post_msg_by_znode_p (zi, nodes + old_active,
|
|
MSG_NCACTIVATE, FALSE, 0);
|
|
post_msg_by_znode_p (zi, nodes + old_active,
|
|
MSG_ACTIVE, FALSE, 0);
|
|
post_msg_by_znode_p (zi, nodes + old_active,
|
|
MSG_KILLFOCUS, (WPARAM)new_hwnd, 0);
|
|
}
|
|
|
|
if (idx_znode) {
|
|
post_msg_by_znode_p (zi, nodes + idx_znode,
|
|
MSG_NCACTIVATE, TRUE, 0);
|
|
post_msg_by_znode_p (zi, nodes + idx_znode,
|
|
MSG_ACTIVE, TRUE, 0);
|
|
post_msg_by_znode_p (zi, nodes + idx_znode,
|
|
MSG_SETFOCUS, (WPARAM)old_hwnd, 0);
|
|
}
|
|
|
|
return old_hwnd;
|
|
}
|
|
|
|
#if 0 /* Since 4.2.0, use strdup to duplicate the caption */
|
|
static void get_text_char_pos (PLOGFONT log_font, const char *text,
|
|
int len, int fit_bytes, int *fit_chars, int *pos_chars)
|
|
{
|
|
DEVFONT* sbc_devfont = log_font->devfonts[0];
|
|
DEVFONT* mbc_devfont = log_font->devfonts[1];
|
|
int len_cur_char;
|
|
int left_bytes = len;
|
|
int char_count = 0, bytes = 0;
|
|
|
|
while (left_bytes > 0 && bytes < fit_bytes) {
|
|
if (pos_chars) {
|
|
pos_chars[char_count] = len - left_bytes;
|
|
}
|
|
if ((mbc_devfont) &&
|
|
(len_cur_char = mbc_devfont->charset_ops->len_first_char
|
|
((const unsigned char*)text, left_bytes)) > 0) {
|
|
char_count ++;
|
|
left_bytes -= len_cur_char;
|
|
text += len_cur_char;
|
|
bytes += len_cur_char;
|
|
} else {
|
|
if ((len_cur_char = sbc_devfont->charset_ops->len_first_char
|
|
((const unsigned char*)text, left_bytes)) > 0) {
|
|
char_count ++;
|
|
left_bytes -= len_cur_char;
|
|
text += len_cur_char;
|
|
bytes += len_cur_char;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fit_chars) {
|
|
*fit_chars = char_count;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Since 4.2.0:
|
|
Under compositing schema, we do not allocate mask rectangles
|
|
for round corners. Instead, we get the region of window znode
|
|
in ServerGetWinZNodeRegion.
|
|
*/
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
|
|
#define do_with_round_rect(src, drc, idx) \
|
|
if (idx != 0) { \
|
|
if (drc[idx-1].left == src.left && \
|
|
RECTW(drc[idx-1]) == RECTW(src)) { \
|
|
SetRect(&(drc[idx-1]), \
|
|
drc[idx-1].left, \
|
|
drc[idx-1].top, \
|
|
drc[idx-1].right, \
|
|
src.bottom); \
|
|
} \
|
|
else { \
|
|
CopyRect(&(drc[idx]), &src); \
|
|
idx++; \
|
|
} \
|
|
} \
|
|
else { \
|
|
CopyRect(&(drc[idx]), &src); \
|
|
idx++; \
|
|
}
|
|
|
|
static int alloc_mask_rects_for_round_corners (ZORDERINFO* zi,
|
|
ZORDERNODE* node, const DWORD flags, const RECT *rc)
|
|
{
|
|
RECT* roundrc = NULL;
|
|
RECT rect;
|
|
int max_rect_num = 1, free_slot, rc_idx;
|
|
int i, z, r = RADIUS_WINDOW_CORNERS;
|
|
unsigned short idx;
|
|
MASKRECT *firstmaskrect;
|
|
|
|
if (flags & ZOF_TW_TROUNDCNS)
|
|
max_rect_num += r;
|
|
if (flags & ZOF_TW_BROUNDCNS)
|
|
max_rect_num += r;
|
|
|
|
roundrc = calloc (1, max_rect_num * sizeof(RECT));
|
|
if (!roundrc)
|
|
return -1;
|
|
|
|
/*generate region of top round corner*/
|
|
rc_idx = 0;
|
|
if (flags & ZOF_TW_TROUNDCNS) {
|
|
for(i = 0; i < r; i++)
|
|
{
|
|
z = sqrt (2*i*r - i*i);
|
|
SetRect (&rect, rc->left+r-z, rc->top+i,
|
|
rc->left+RECTWP(rc)-r+z, rc->top+i+1);
|
|
do_with_round_rect (rect, roundrc, rc_idx);
|
|
}
|
|
}
|
|
else{
|
|
SetRect (&rect, rc->left, rc->top,
|
|
rc->left+RECTWP(rc), rc->top+r);
|
|
CopyRect (&(roundrc[rc_idx]), &rect);
|
|
rc_idx++;
|
|
}
|
|
|
|
SetRect (&rect, rc->left, rc->top+r,
|
|
rc->left+RECTWP(rc), rc->top+RECTHP(rc)-r);
|
|
do_with_round_rect (rect, roundrc, rc_idx);
|
|
|
|
/* generate region of bottom round corner*/
|
|
if (flags & ZOF_TW_BROUNDCNS) {
|
|
for(i = 1; i < r; i++)
|
|
{
|
|
z = sqrt (r*r-i*i);
|
|
SetRect (&rect, rc->left+r-z,
|
|
rc->top+RECTHP(rc)-r+i-1,
|
|
rc->left+RECTWP(rc)-r+z,
|
|
rc->top+RECTHP(rc)-r+i+1);
|
|
|
|
do_with_round_rect (rect, roundrc, rc_idx);
|
|
}
|
|
}
|
|
else {
|
|
SetRect (&rect, rc->left, rc->top+RECTHP(rc)-r,
|
|
rc->left+RECTWP(rc), rc->top+RECTHP(rc));
|
|
do_with_round_rect (rect, roundrc, rc_idx);
|
|
}
|
|
|
|
/* if have enough mask rect */
|
|
if (rc_idx >
|
|
__mg_get_nr_idle_slots ((unsigned char*)GET_MASKRECT_USAGEBMP(zi),
|
|
zi->size_maskrect_usage_bmp)) {
|
|
free (roundrc);
|
|
return -1;
|
|
}
|
|
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
|
|
/* allocate space*/
|
|
idx = 0;
|
|
for (i = 0; i < rc_idx; i++) {
|
|
free_slot = __mg_lookfor_unused_slot (
|
|
(unsigned char*)GET_MASKRECT_USAGEBMP(zi),
|
|
zi->size_maskrect_usage_bmp, 1);
|
|
if (free_slot == -1) {
|
|
_WRN_PRINTF ("KERNEL: __mg_lookfor_unused_slot failed\n");
|
|
return -1;
|
|
}
|
|
|
|
(firstmaskrect + free_slot)->prev = idx;
|
|
if (idx != 0) {
|
|
(firstmaskrect + idx)->next = free_slot;
|
|
}
|
|
else {
|
|
node->idx_mask_rect = free_slot;
|
|
}
|
|
|
|
idx = free_slot;
|
|
}
|
|
|
|
if (idx != 0) {
|
|
(firstmaskrect + idx)->prev = 0;
|
|
}
|
|
|
|
/* get value */
|
|
idx = node->idx_mask_rect;
|
|
i = 0;
|
|
while (idx != 0) {
|
|
(firstmaskrect + idx)->left = (unsigned short)roundrc[i].left;
|
|
(firstmaskrect + idx)->top = (unsigned short)roundrc[i].top;
|
|
(firstmaskrect + idx)->right = (unsigned short)roundrc[i].right;
|
|
(firstmaskrect + idx)->bottom = (unsigned short)roundrc[i].bottom;
|
|
idx = (firstmaskrect + idx)->next;
|
|
i++;
|
|
}
|
|
|
|
free (roundrc);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
static inline int validate_compositing_type (DWORD flags, int type)
|
|
{
|
|
if (flags & ZOF_TF_CONTROL) {
|
|
return CT_OPAQUE;
|
|
}
|
|
else if (type < CT_OPAQUE || type > CT_MAX_VALUE)
|
|
return CT_OPAQUE;
|
|
|
|
return type;
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
static int AllocZOrderNodeEx (ZORDERINFO* zi, int cli, HWND hwnd, HWND main_win,
|
|
DWORD flags, const RECT *rc, const char *caption,
|
|
HDC mem_dc, int ct, DWORD ct_arg)
|
|
{
|
|
DWORD type = flags & ZOF_TYPE_MASK;
|
|
int *first = NULL, *nr_nodes = NULL;
|
|
int free_slot = -1, old_first;
|
|
ZORDERNODE* nodes;
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
/* Since 4.2.0: check fixed znode type first */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
if (nodes [ZNIDX_SCREENLOCK].hwnd) {
|
|
flags &= ~ZOF_TYPE_MASK;
|
|
flags |= ZOF_TYPE_TOPMOST;
|
|
}
|
|
else {
|
|
free_slot = ZNIDX_SCREENLOCK;
|
|
}
|
|
break;
|
|
|
|
case ZOF_TYPE_DOCKER:
|
|
if (nodes [ZNIDX_DOCKER].hwnd) {
|
|
flags &= ~ZOF_TYPE_MASK;
|
|
flags |= ZOF_TYPE_TOPMOST;
|
|
}
|
|
else {
|
|
free_slot = ZNIDX_DOCKER;
|
|
}
|
|
break;
|
|
|
|
case ZOF_TYPE_LAUNCHER:
|
|
if (nodes [ZNIDX_LAUNCHER].hwnd) {
|
|
flags &= ~ZOF_TYPE_MASK;
|
|
flags |= ZOF_TYPE_NORMAL;
|
|
}
|
|
else {
|
|
free_slot = ZNIDX_LAUNCHER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* reacquire type */
|
|
type = flags & ZOF_TYPE_MASK;
|
|
switch (type) {
|
|
case ZOF_TYPE_GLOBAL:
|
|
if (zi->nr_globals < zi->max_nr_globals) {
|
|
first = &zi->first_global;
|
|
nr_nodes = &zi->nr_globals;
|
|
}
|
|
break;
|
|
case ZOF_TYPE_TOPMOST:
|
|
if (zi->nr_topmosts < zi->max_nr_topmosts) {
|
|
first = &zi->first_topmost;
|
|
nr_nodes = &zi->nr_topmosts;
|
|
}
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
if (zi->nr_normals < zi->max_nr_normals) {
|
|
first = &zi->first_normal;
|
|
nr_nodes = &zi->nr_normals;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (free_slot == -1 && first == NULL) {
|
|
_ERR_PRINTF ("Cann't find first zorder node.\n");
|
|
return -1;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0 && flags & ZOF_VISIBLE)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
/* the slot must be larger than zero */
|
|
if (free_slot == -1) {
|
|
if (type == ZOF_TYPE_GLOBAL)
|
|
free_slot = __mg_lookfor_unused_slot ((BYTE*)(zi + 1),
|
|
zi->max_nr_globals, 1);
|
|
else {
|
|
free_slot = __mg_lookfor_unused_slot ((BYTE*)(zi + 1)
|
|
+ (zi->max_nr_globals >> 3),
|
|
zi->size_usage_bmp - (zi->max_nr_globals >> 3), 1);
|
|
|
|
if (free_slot >= 0) {
|
|
free_slot += zi->max_nr_globals;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-1 == free_slot) {
|
|
/* unlock zorderinfo for change. */
|
|
unlock_zi_for_change (zi);
|
|
_ERR_PRINTF ("Cann't find unused slot. \n");
|
|
return -1;
|
|
}
|
|
|
|
nodes [free_slot].flags = flags;
|
|
nodes [free_slot].rc = *rc;
|
|
nodes [free_slot].cli = cli;
|
|
nodes [free_slot].hwnd = hwnd;
|
|
nodes [free_slot].main_win = main_win;
|
|
nodes [free_slot].lock_count = 0;
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
nodes [free_slot].changes = 0;
|
|
nodes [free_slot].ct = validate_compositing_type (flags, ct);
|
|
nodes [free_slot].ct_arg = ct_arg;
|
|
nodes [free_slot].mem_dc = mem_dc;
|
|
nodes [free_slot].dirty_rcs = NULL;
|
|
#else
|
|
nodes [free_slot].age = 1;
|
|
nodes [free_slot].dirty_rc.left = 0;
|
|
nodes [free_slot].dirty_rc.top = 0;
|
|
nodes [free_slot].dirty_rc.right = 0;
|
|
nodes [free_slot].dirty_rc.bottom = 0;
|
|
#endif
|
|
nodes [free_slot].idx_mask_rect = 0;
|
|
nodes [free_slot].priv_data = NULL;
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
if (flags & ZOF_TW_TROUNDCNS || flags & ZOF_TW_BROUNDCNS) {
|
|
RECT cli_rect;
|
|
|
|
SetRect(&cli_rect, 0, 0, RECTW(nodes[free_slot].rc),
|
|
RECTH(nodes[free_slot].rc));
|
|
alloc_mask_rects_for_round_corners (__mg_zorder_info,
|
|
&nodes[free_slot], flags, &cli_rect);
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
if (caption) {
|
|
#if 0 /* Since 4.2.0, use strdup to duplicate the caption */
|
|
PLOGFONT menufont;
|
|
int fit_chars, pos_chars[MAX_CAPTION_LEN], caplen;
|
|
|
|
menufont = GetSystemFont (SYSLOGFONT_MENU);
|
|
caplen = strlen(caption);
|
|
|
|
if (caplen < 32) {
|
|
strcpy (nodes[free_slot].caption, caption);
|
|
}
|
|
else {
|
|
int tail_pos;
|
|
get_text_char_pos (menufont, caption, caplen, (32 - 3), /* '...' = 3*/
|
|
&fit_chars, pos_chars);
|
|
|
|
tail_pos = pos_chars[fit_chars-1];
|
|
|
|
if ((tail_pos + 3) >= 32 && fit_chars > 4) {
|
|
tail_pos = pos_chars[fit_chars-2];
|
|
if (tail_pos + 3 >= 32) {
|
|
tail_pos = pos_chars[fit_chars-3];
|
|
if (tail_pos + 3 >= 32) {
|
|
tail_pos = pos_chars[fit_chars-4];
|
|
}
|
|
}
|
|
}
|
|
memcpy(nodes[free_slot].caption, caption, tail_pos);
|
|
strcpy ((nodes[free_slot].caption + tail_pos), "...");
|
|
}
|
|
#else
|
|
nodes[free_slot].caption = strdup (caption);
|
|
_MG_PRINTF("Caption of ZNODE: %s\n", caption);
|
|
#endif
|
|
}
|
|
else {
|
|
nodes[free_slot].caption = NULL;
|
|
}
|
|
|
|
/* check influenced zorder nodes */
|
|
if (flags & ZOF_VISIBLE) {
|
|
/* Since 4.2.0 */
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
int slot;
|
|
RECT rc_screen = GetScreenRect();
|
|
|
|
if (type >= ZOF_TYPE_LAUNCHER) {
|
|
slot = ZNIDX_LAUNCHER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
|
|
if (type >= ZOF_TYPE_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type >= ZOF_TYPE_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type >= ZOF_TYPE_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type >= ZOF_TYPE_DOCKER) {
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
|
|
if (type >= ZOF_TYPE_SCREENLOCK) {
|
|
slot = ZNIDX_SCREENLOCK;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&nodes [free_slot].rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
|
|
/* for destkop */
|
|
if (DoesIntersect (&nodes [free_slot].rc, &rc_screen)) {
|
|
nodes [0].age++;
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
DO_COMPSOR_OP_ARGS (on_showing_win,
|
|
__mg_get_layer_from_zi(zi), free_slot);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
}
|
|
|
|
#if 1
|
|
/* Since 4.2.0. Support for always top znode. */
|
|
if (first) { // not a fixed znode
|
|
if (*first == 0 ||
|
|
(nodes [*first].flags & ZOF_IF_ALWAYSTOP) != ZOF_IF_ALWAYSTOP)
|
|
{
|
|
old_first = *first;
|
|
nodes [old_first].prev = free_slot;
|
|
nodes [free_slot].prev = 0;
|
|
nodes [free_slot].next = old_first;
|
|
}
|
|
else {
|
|
int pre_idx = *first;
|
|
while (*first) {
|
|
if ((nodes [*first].flags & ZOF_IF_ALWAYSTOP) ==
|
|
ZOF_IF_ALWAYSTOP) {
|
|
pre_idx = *first;
|
|
first = &nodes[*first].next;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
old_first = pre_idx;
|
|
nodes [free_slot].prev = old_first;
|
|
nodes [free_slot].next = nodes [old_first].next;
|
|
nodes [nodes [old_first].next].prev = free_slot;
|
|
nodes [old_first].next = free_slot;
|
|
}
|
|
|
|
if (first == &zi->first_global || first == &zi->first_topmost
|
|
|| first == &zi->first_normal) {
|
|
*first = free_slot;
|
|
}
|
|
}
|
|
#else
|
|
if (first) { // not a fixed znode
|
|
/* chain the new node */
|
|
old_first = *first;
|
|
nodes [old_first].prev = free_slot;
|
|
nodes [free_slot].prev = 0;
|
|
nodes [free_slot].next = old_first;
|
|
*first = free_slot;
|
|
}
|
|
#endif
|
|
|
|
if (nr_nodes)
|
|
*nr_nodes += 1;
|
|
|
|
/* unlock zi for change ... */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return free_slot;
|
|
}
|
|
|
|
static inline int AllocZOrderNode (int cli, HWND hwnd, HWND main_win,
|
|
DWORD flags, const RECT *rc, const char *caption,
|
|
HDC mem_dc, int ct, DWORD ct_arg)
|
|
{
|
|
return AllocZOrderNodeEx (get_zorder_info(cli), cli, hwnd, main_win,
|
|
flags, rc, caption, mem_dc, ct, ct_arg);
|
|
}
|
|
|
|
static int FreeZOrderNodeEx (ZORDERINFO* zi, int idx_znode, HDC* memdc)
|
|
{
|
|
DWORD flags, type;
|
|
RECT rc;
|
|
int *first = NULL, *nr_nodes = NULL;
|
|
ZORDERNODE* nodes;
|
|
int old_active, next_active;
|
|
int fixed_idx;
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
MG_Layer* layer = __mg_get_layer_from_zi(zi);
|
|
#endif
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0 && nodes [idx_znode].flags & ZOF_VISIBLE)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
flags = nodes [idx_znode].flags;
|
|
type = flags & ZOF_TYPE_MASK;
|
|
rc = nodes [idx_znode].rc;
|
|
|
|
/* Since 4.2.0 */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
fixed_idx = ZNIDX_SCREENLOCK;
|
|
first = &fixed_idx;
|
|
break;
|
|
|
|
case ZOF_TYPE_DOCKER:
|
|
fixed_idx = ZNIDX_DOCKER;
|
|
first = &fixed_idx;
|
|
break;
|
|
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = &zi->first_global;
|
|
nr_nodes = &zi->nr_globals;
|
|
break;
|
|
|
|
case ZOF_TYPE_TOPMOST:
|
|
if (zi->nr_topmosts < zi->max_nr_topmosts) {
|
|
first = &zi->first_topmost;
|
|
nr_nodes = &zi->nr_topmosts;
|
|
}
|
|
break;
|
|
|
|
case ZOF_TYPE_NORMAL:
|
|
if (zi->nr_normals < zi->max_nr_normals) {
|
|
first = &zi->first_normal;
|
|
nr_nodes = &zi->nr_normals;
|
|
}
|
|
break;
|
|
|
|
case ZOF_TYPE_LAUNCHER:
|
|
fixed_idx = ZNIDX_LAUNCHER;
|
|
first = &fixed_idx;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (first == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
if (memdc)
|
|
*memdc = nodes[idx_znode].mem_dc;
|
|
#endif
|
|
|
|
/* please lock zi for change*/
|
|
lock_zi_for_change (zi);
|
|
|
|
/* Since 4.2.0, use strdup to duplicate the caption */
|
|
if (nodes[idx_znode].caption) {
|
|
free (nodes[idx_znode].caption);
|
|
nodes[idx_znode].caption = NULL;
|
|
}
|
|
|
|
/* Free round corners mask rect. */
|
|
if (flags & ZOF_TW_TROUNDCNS || flags & ZOF_TW_BROUNDCNS) {
|
|
clean_znode_maskrect (zi, nodes, idx_znode);
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
SetClipRgn (&sg_UpdateRgn, &nodes [idx_znode].rc);
|
|
|
|
/* check influenced zorder nodes */
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE) {
|
|
int slot;
|
|
RECT rc_screen = GetScreenRect ();
|
|
|
|
slot = nodes [idx_znode].next;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
/* Since 4.2.0 */
|
|
if (type > ZOF_TYPE_DOCKER) {
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_LAUNCHER) {
|
|
slot = ZNIDX_LAUNCHER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
if (SubtractClipRect (&sg_UpdateRgn, &rc_screen)) {
|
|
nodes [0].age++;
|
|
nodes [0].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE) {
|
|
DO_COMPSOR_OP_ARGS (on_hiding_win, layer, idx_znode);
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* XXX: get next activable window znode before freeing the current znode */
|
|
next_active = get_next_activable_mainwin (zi, idx_znode);
|
|
old_active = zi->active_win;
|
|
if (idx_znode == zi->active_win)
|
|
zi->active_win = 0;
|
|
|
|
if (first == &fixed_idx) {
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
nodes [idx_znode].hwnd = HWND_NULL;
|
|
nodes [idx_znode].cli = -1;
|
|
nodes [idx_znode].flags &= ~ZOF_VISIBLE;
|
|
}
|
|
else if (*first == idx_znode) {
|
|
/* unchain it */
|
|
unchain_znode ((unsigned char*)(zi+1), nodes, idx_znode);
|
|
nodes [idx_znode].hwnd = HWND_NULL;
|
|
nodes [idx_znode].cli = -1;
|
|
|
|
*first = nodes [idx_znode].next;
|
|
*nr_nodes -= 1;
|
|
}
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
/* update all znode if it's dirty */
|
|
do_for_all_znodes (&rc, zi, _cb_update_znode, ZT_ALL);
|
|
|
|
if (nodes [0].flags & ZOF_IF_REFERENCE) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ERASEDESKTOP, 0, (WPARAM)&rc);
|
|
nodes [0].flags &= ~ZOF_IF_REFERENCE;
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
if (flags & ZOF_VISIBLE) {
|
|
DO_COMPSOR_OP_ARGS (on_dirty_screen,
|
|
layer, flags & ZOF_TYPE_FLAG_MASK, &rc);
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* if active_win is this window, change it */
|
|
if (idx_znode == old_active) {
|
|
dskSetActiveZOrderNode (nodes [next_active].cli, next_active);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int FreeZOrderNode (int cli, int idx_znode, HDC* memdc)
|
|
{
|
|
return FreeZOrderNodeEx (get_zorder_info(cli), idx_znode, memdc);
|
|
}
|
|
|
|
static DWORD get_znode_flags_from_style (PMAINWIN pWin)
|
|
{
|
|
DWORD zt_type = 0;
|
|
|
|
#if defined(_MGRM_PROCESSES)
|
|
if (mgIsServer) {
|
|
/* Always be global ones */
|
|
zt_type |= ZOF_TYPE_GLOBAL;
|
|
} else
|
|
#endif
|
|
{
|
|
/* Since 4.2.0 */
|
|
switch (pWin->dwExStyle & WS_EX_WINTYPE_MASK) {
|
|
case WS_EX_WINTYPE_SCREENLOCK:
|
|
zt_type |= ZOF_TYPE_SCREENLOCK;
|
|
break;
|
|
|
|
case WS_EX_WINTYPE_DOCKER:
|
|
zt_type |= ZOF_TYPE_DOCKER;
|
|
break;
|
|
|
|
case WS_EX_WINTYPE_LAUNCHER:
|
|
zt_type |= ZOF_TYPE_LAUNCHER;
|
|
break;
|
|
|
|
default:
|
|
if (pWin->dwExStyle & WS_EX_TOPMOST)
|
|
zt_type |= ZOF_TYPE_TOPMOST;
|
|
else if (pWin->WinType == TYPE_CONTROL &&
|
|
(pWin->pMainWin->dwExStyle & WS_EX_TOPMOST))
|
|
zt_type |= ZOF_TYPE_TOPMOST;
|
|
else
|
|
zt_type |= ZOF_TYPE_NORMAL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* XXX: Since 4.2.0 */
|
|
if (!(pWin->dwStyle & WS_CHILD)) {
|
|
if (pWin->dwStyle & WS_MINIMIZE) {
|
|
zt_type |= ZOF_MINIMIZED;
|
|
}
|
|
else if (pWin->dwStyle & WS_MAXIMIZE) {
|
|
zt_type |= ZOF_MAXIMIZED;
|
|
/* TODO: change main window rect here */
|
|
}
|
|
}
|
|
|
|
if (pWin->dwStyle & WS_VISIBLE) {
|
|
zt_type |= ZOF_VISIBLE;
|
|
}
|
|
|
|
if (pWin->dwStyle & WS_DISABLED)
|
|
zt_type |= ZOF_DISABLED;
|
|
|
|
/* Since 4.2.0 */
|
|
if (pWin->dwStyle & WS_ALWAYSTOP)
|
|
zt_type |= ZOF_IF_ALWAYSTOP;
|
|
|
|
if (pWin->WinType == TYPE_MAINWIN) {
|
|
if (pWin->dwExStyle & WS_EX_TOOLWINDOW)
|
|
zt_type |= ZOF_TF_TOOLWIN;
|
|
else
|
|
zt_type |= ZOF_TF_MAINWIN;
|
|
}
|
|
else
|
|
zt_type |= ZOF_TF_CONTROL;
|
|
|
|
if (pWin->dwExStyle & WS_EX_TROUNDCNS)
|
|
zt_type |= ZOF_TW_TROUNDCNS;
|
|
|
|
if (pWin->dwExStyle & WS_EX_BROUNDCNS)
|
|
zt_type |= ZOF_TW_BROUNDCNS;
|
|
|
|
return zt_type;
|
|
}
|
|
|
|
static int AllocZOrderMaskRect (int cli, int idx_znode,
|
|
int flags, const RECT4MASK *rc, const int nr_rc)
|
|
{
|
|
MASKRECT *firstmaskrect;
|
|
ZORDERNODE* nodes;
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
int free_slot, i, cur_idx, idx, old_num = 0;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
|
|
/*get mask rect number*/
|
|
idx = nodes[idx_znode].idx_mask_rect;
|
|
|
|
while(idx) {
|
|
old_num++;
|
|
idx = ((MASKRECT *)(firstmaskrect+idx))->next;
|
|
}
|
|
|
|
if (nr_rc > old_num) {
|
|
/* check the number of mask rect if enough */
|
|
int idle =
|
|
__mg_get_nr_idle_slots((unsigned char*)GET_MASKRECT_USAGEBMP(zi),
|
|
zi->size_maskrect_usage_bmp);
|
|
if (idle < nr_rc-old_num) {
|
|
unlock_zi_for_change (zi);
|
|
return -1;
|
|
}
|
|
|
|
/*add new space to Znode*/
|
|
idx = nodes[idx_znode].idx_mask_rect;
|
|
for(i = 0; i < nr_rc-old_num; i++) {
|
|
free_slot = __mg_lookfor_unused_slot (
|
|
(unsigned char*)GET_MASKRECT_USAGEBMP(zi),
|
|
zi->size_maskrect_usage_bmp, 1);
|
|
if (free_slot == -1) {
|
|
unlock_zi_for_change (zi);
|
|
return -1;
|
|
}
|
|
|
|
(firstmaskrect+free_slot)->next = idx;
|
|
if (idx != 0) {
|
|
(firstmaskrect+idx)->prev = free_slot;
|
|
}
|
|
idx = free_slot;
|
|
}
|
|
|
|
if (idx != 0) {
|
|
(firstmaskrect+idx)->prev = 0;
|
|
}
|
|
}
|
|
else {
|
|
for(i =0; i < old_num-nr_rc; i++) {
|
|
idx = nodes[idx_znode].idx_mask_rect;
|
|
__mg_slot_clear_use((unsigned char*)GET_MASKRECT_USAGEBMP(zi), idx);
|
|
idx = ((MASKRECT *)(firstmaskrect+idx))->next;
|
|
}
|
|
}
|
|
|
|
nodes[idx_znode].idx_mask_rect = idx;
|
|
|
|
/* the slot must be larger than zero */
|
|
i = 0;
|
|
cur_idx = nodes[idx_znode].idx_mask_rect;
|
|
while(cur_idx) {
|
|
/* there is no slots in the bitmap */
|
|
(firstmaskrect+cur_idx)->left = rc[i].left;
|
|
(firstmaskrect+cur_idx)->top = rc[i].top;
|
|
(firstmaskrect+cur_idx)->right = rc[i].right;
|
|
(firstmaskrect+cur_idx)->bottom = rc[i].bottom;
|
|
|
|
cur_idx = (firstmaskrect+cur_idx)->next;
|
|
i++;
|
|
}
|
|
|
|
/* unlock zi for change ... */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int FreeZOrderMaskRect (int cli, int idx_znode)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#if 0
|
|
int idx, tmp;
|
|
MASKRECT *first;
|
|
first = GET_MASKRECT(zi);
|
|
idx = nodes [idx_znode].idx_mask_rect;
|
|
|
|
while(idx) {
|
|
__mg_slot_clear_use((unsigned char*)GET_MASKRECT_USAGEBMP(zi), idx);
|
|
(first+idx)->prev = 0;
|
|
tmp = (first+idx)->next;
|
|
(first+idx)->next = 0;
|
|
idx = tmp;
|
|
}
|
|
|
|
nodes[idx_znode].idx_mask_rect = 0;
|
|
#else
|
|
clean_znode_maskrect (zi, nodes, idx_znode);
|
|
#endif
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
return 0;
|
|
}
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
static int update_client_window_rgn (int cli, HWND hwnd);
|
|
#endif
|
|
|
|
static int dskMove2Top (int cli, int idx_znode);
|
|
static int dskShowWindow (int cli, int idx_znode);
|
|
static int dskHideWindow (int cli, int idx_znode);
|
|
static ZORDERINFO* get_zorder_info (int cli);
|
|
|
|
#ifdef _MG_ENABLE_SCREENSAVER
|
|
static void dskRefreshAllClient (const RECT* invrc)
|
|
{
|
|
#if defined(_MGRM_PROCESSES)
|
|
if (mgIsServer) {
|
|
ZORDERINFO* zi = get_zorder_info (0);
|
|
SendMessage (HWND_DESKTOP, MSG_ERASEDESKTOP, 0,
|
|
(LPARAM)(invrc));
|
|
|
|
lock_zi_for_read (zi);
|
|
SetClipRgn (&sg_UpdateRgn, invrc);
|
|
/* check influenced window zorder nodes */
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_ALL);
|
|
/* update all znode if it's dirty */
|
|
do_for_all_znodes ((void*)invrc, zi, _cb_update_znode, ZT_ALL);
|
|
unlock_zi_for_read (zi);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static int dskCreateTopZOrderNode (int cli, const RECT *rc)
|
|
{
|
|
int idx_znode = 0;
|
|
int zt_type = ZOF_VISIBLE | ZOF_TF_MAINWIN;
|
|
|
|
#if defined(_MGRM_PROCESSES)
|
|
if (mgIsServer) {
|
|
zt_type |= ZOF_TYPE_GLOBAL;
|
|
} else
|
|
#endif
|
|
zt_type |= ZOF_TYPE_TOPMOST;
|
|
|
|
idx_znode = AllocZOrderNode (0, 0,
|
|
(HWND)0,
|
|
zt_type,
|
|
rc, "", HDC_SCREEN_SYS);
|
|
dskShowWindow (cli, idx_znode);
|
|
return idx_znode;
|
|
}
|
|
|
|
static int dskDestroyTopZOrderNode (int cli, int idx_znode)
|
|
{
|
|
return FreeZOrderNode (cli, idx_znode, NULL);
|
|
}
|
|
|
|
static int _screensaver_node;
|
|
|
|
void __mg_screensaver_show(void)
|
|
{
|
|
dskShowWindow (0, _screensaver_node);
|
|
dskMove2Top (0, _screensaver_node);
|
|
}
|
|
|
|
void __mg_screensaver_hide(void)
|
|
{
|
|
dskHideWindow (0, _screensaver_node);
|
|
}
|
|
|
|
void __mg_screensaver_create(void)
|
|
{
|
|
/* create screensaver node. */
|
|
if (!_screensaver_node) {
|
|
RECT rcScr = GetScreenRect();
|
|
_screensaver_node = dskCreateTopZOrderNode (0, &rcScr);
|
|
dskSetZNodeAlwaysTop (0, _screensaver_node, TRUE);
|
|
dskHideWindow (0, _screensaver_node);
|
|
}
|
|
}
|
|
|
|
void __mg_screensaver_destroy(void)
|
|
{
|
|
/* destroy screensaver node. */
|
|
if (_screensaver_node) {
|
|
dskDestroyTopZOrderNode(0, _screensaver_node);
|
|
_screensaver_node = 0;
|
|
}
|
|
}
|
|
#endif /* defined _MG_ENABLE_SCREENSAVER */
|
|
|
|
static int dskSetZNodeAlwaysTop (int cli, int idx_znode, BOOL fSet)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info (cli);
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
if (fSet) {
|
|
nodes[idx_znode].flags |= ZOF_IF_ALWAYSTOP;
|
|
}
|
|
else {
|
|
nodes[idx_znode].flags &= ~ZOF_IF_ALWAYSTOP;
|
|
}
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
/* Since 4.2.0 */
|
|
static int dskSetZNodeCompositing (int cli, int idx_znode, int ct, DWORD ct_arg)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info (cli);
|
|
DWORD type;
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
type = nodes[idx_znode].flags & ZOF_TYPE_MASK;
|
|
if (type == ZOF_TYPE_NULL || type >= ZOF_TYPE_DESKTOP) {
|
|
return -1;
|
|
}
|
|
|
|
if ((nodes[idx_znode].ct == ct) && (nodes[idx_znode].ct_arg == ct_arg)) {
|
|
return 0;
|
|
}
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
nodes [idx_znode].ct = ct;
|
|
nodes [idx_znode].ct_arg = ct_arg;
|
|
|
|
DO_COMPSOR_OP_ARGS (on_changed_ct,
|
|
get_layer_from_client (cli), idx_znode);
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
return 0;
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
static int dskMove2Top (int cli, int idx_znode)
|
|
{
|
|
DWORD type;
|
|
ZORDERINFO* zi = get_zorder_info (cli);
|
|
int *first = NULL, fixed_idx;
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
if (idx_znode <= ZNIDX_LAUNCHER)
|
|
return -1;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
type = nodes [idx_znode].flags & ZOF_TYPE_MASK;
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
fixed_idx = ZNIDX_SCREENLOCK;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_DOCKER:
|
|
fixed_idx = ZNIDX_DOCKER;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = &zi->first_global;
|
|
break;
|
|
case ZOF_TYPE_TOPMOST:
|
|
first = &zi->first_topmost;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
first = &zi->first_normal;
|
|
break;
|
|
case ZOF_TYPE_LAUNCHER:
|
|
fixed_idx = ZNIDX_LAUNCHER;
|
|
first = &fixed_idx;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (first == NULL || *first == idx_znode)
|
|
return -1;
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
EmptyClipRgn (&sg_UpdateRgn);
|
|
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE) {
|
|
int slot;
|
|
RECT rc = nodes [idx_znode].rc;
|
|
|
|
if (type == ZOF_TYPE_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot != idx_znode; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
AddClipRect(&sg_UpdateRgn, &nodes [slot].rc);
|
|
}
|
|
}
|
|
}
|
|
if (type == ZOF_TYPE_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot != idx_znode; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
AddClipRect (&sg_UpdateRgn, &nodes [slot].rc);
|
|
}
|
|
}
|
|
}
|
|
if (type == ZOF_TYPE_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot != idx_znode; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
AddClipRect (&sg_UpdateRgn, &nodes [slot].rc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* unchain it and move to top */
|
|
if (nodes [idx_znode].prev) {
|
|
nodes [nodes [idx_znode].prev].next = nodes [idx_znode].next;
|
|
}
|
|
if (nodes [idx_znode].next) {
|
|
nodes [nodes [idx_znode].next].prev = nodes [idx_znode].prev;
|
|
}
|
|
|
|
#if 1
|
|
/* Since 4.2.0. Support for always top znode. */
|
|
if (!(*first) ||
|
|
((nodes [*first].flags & ZOF_IF_ALWAYSTOP) != ZOF_IF_ALWAYSTOP)) {
|
|
nodes [idx_znode].prev = nodes[*first].prev;
|
|
nodes [idx_znode].next = *first;
|
|
nodes [*first].prev = idx_znode;
|
|
}
|
|
else {
|
|
int pre_idx = *first;
|
|
while (*first) {
|
|
if ((nodes [*first].flags & ZOF_IF_ALWAYSTOP) == ZOF_IF_ALWAYSTOP) {
|
|
pre_idx = *first;
|
|
first = &nodes[*first].next;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
nodes [idx_znode].prev = pre_idx;
|
|
nodes [idx_znode].next = nodes [pre_idx].next;
|
|
nodes [nodes[pre_idx].next].prev = idx_znode;
|
|
nodes [pre_idx].next = idx_znode;
|
|
}
|
|
|
|
if (first == &zi->first_global || first == &zi->first_topmost
|
|
|| first == &zi->first_normal) {
|
|
*first = idx_znode;
|
|
}
|
|
#else
|
|
nodes [idx_znode].prev = 0;
|
|
nodes [idx_znode].next = *first;
|
|
nodes [*first].prev = idx_znode;
|
|
*first = idx_znode;
|
|
#endif
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
DO_COMPSOR_OP_ARGS (on_raised_win, get_layer_from_client (cli), idx_znode);
|
|
#else
|
|
nodes [idx_znode].age++;
|
|
#endif
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
if ((nodes [idx_znode].flags & ZOF_VISIBLE) && nodes [idx_znode].hwnd) {
|
|
update_client_window_rgn (nodes [idx_znode].cli,
|
|
nodes [idx_znode].hwnd);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dskShowWindow (int cli, int idx_znode)
|
|
{
|
|
DWORD type;
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* nodes;
|
|
int *first = NULL, fixed_idx;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals) ||
|
|
idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
nodes = GET_ZORDERNODE(__mg_zorder_info);
|
|
type = nodes [idx_znode].flags & ZOF_TYPE_MASK;
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
fixed_idx = ZNIDX_SCREENLOCK;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_DOCKER:
|
|
fixed_idx = ZNIDX_DOCKER;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = &zi->first_global;
|
|
break;
|
|
case ZOF_TYPE_TOPMOST:
|
|
first = &zi->first_topmost;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
first = &zi->first_normal;
|
|
break;
|
|
case ZOF_TYPE_LAUNCHER:
|
|
fixed_idx = ZNIDX_LAUNCHER;
|
|
first = &fixed_idx;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (first == NULL)
|
|
return -1;
|
|
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE)
|
|
return 0;
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
{
|
|
int slot;
|
|
RECT rc = nodes [idx_znode].rc;
|
|
RECT rc_screen = GetScreenRect();
|
|
|
|
if (type > ZOF_TYPE_LAUNCHER) {
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_LAUNCHER);
|
|
}
|
|
if (type > ZOF_TYPE_NORMAL) {
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_NORMAL);
|
|
}
|
|
if (type > ZOF_TYPE_TOPMOST) {
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_TOPMOST);
|
|
}
|
|
if (type > ZOF_TYPE_GLOBAL) {
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_GLOBAL);
|
|
}
|
|
if (type > ZOF_TYPE_DOCKER) {
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_DOCKER);
|
|
}
|
|
if (type > ZOF_TYPE_SCREENLOCK) {
|
|
/* never touch here */
|
|
do_for_all_znodes (&rc, zi, _cb_intersect_rc, ZT_SCREENLOCK);
|
|
}
|
|
|
|
slot = nodes [idx_znode].next;
|
|
for (; slot != 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (&rc, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
|
|
if (DoesIntersect (&rc, &rc_screen)) {
|
|
nodes [0].age++;
|
|
}
|
|
nodes [idx_znode].age++;
|
|
nodes [idx_znode].flags |= ZOF_VISIBLE;
|
|
}
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
nodes [idx_znode].flags |= ZOF_VISIBLE;
|
|
DO_COMPSOR_OP_ARGS (on_showing_win, get_layer_from_client (cli), idx_znode);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
/* unlock zi for change ... */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dskHideWindow (int cli, int idx_znode)
|
|
{
|
|
DWORD type;
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
int *first = NULL, fixed_idx;
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals) {
|
|
return -1;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (zi->cli_trackmenu >= 0)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
type = nodes [idx_znode].flags & ZOF_TYPE_MASK;
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
fixed_idx = ZNIDX_SCREENLOCK;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_DOCKER:
|
|
fixed_idx = ZNIDX_DOCKER;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = &zi->first_global;
|
|
break;
|
|
case ZOF_TYPE_TOPMOST:
|
|
first = &zi->first_topmost;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
first = &zi->first_normal;
|
|
break;
|
|
case ZOF_TYPE_LAUNCHER:
|
|
fixed_idx = ZNIDX_LAUNCHER;
|
|
first = &fixed_idx;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (first == NULL)
|
|
return -1;
|
|
|
|
if (!(nodes[idx_znode].flags & ZOF_VISIBLE)) {
|
|
return 0;
|
|
}
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
/* check influenced zorder nodes */
|
|
SetClipRgn (&sg_UpdateRgn, &nodes [idx_znode].rc);
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE) {
|
|
int slot;
|
|
RECT rcScr = GetScreenRect ();
|
|
|
|
slot = nodes [idx_znode].next;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_DOCKER) {
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_DOCKER);
|
|
}
|
|
if (type > ZOF_TYPE_GLOBAL) {
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_GLOBAL);
|
|
}
|
|
if (type > ZOF_TYPE_TOPMOST) {
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_TOPMOST);
|
|
}
|
|
if (type > ZOF_TYPE_NORMAL) {
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_NORMAL);
|
|
}
|
|
if (type > ZOF_TYPE_LAUNCHER) {
|
|
do_for_all_znodes (&sg_UpdateRgn, zi, _cb_update_rc, ZT_LAUNCHER);
|
|
}
|
|
|
|
if (SubtractClipRect (&sg_UpdateRgn, &rcScr)) {
|
|
nodes [0].age++;
|
|
nodes [0].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
DO_COMPSOR_OP_ARGS (on_hiding_win, get_layer_from_client (cli), idx_znode);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
if (idx_znode && (nodes [idx_znode].flags & ZOF_TF_MAINWIN
|
|
&& (nodes [idx_znode].flags & ZOF_VISIBLE))) {
|
|
post_msg_by_znode_p (zi, nodes + idx_znode, MSG_NCACTIVATE, FALSE, 0);
|
|
post_msg_by_znode_p (zi, nodes + idx_znode, MSG_ACTIVE, FALSE, 0);
|
|
post_msg_by_znode_p (zi, nodes + idx_znode, MSG_KILLFOCUS, 0, 0);
|
|
}
|
|
|
|
nodes [idx_znode].flags &= ~ZOF_VISIBLE;
|
|
/*
|
|
* do not reset the age to zero.
|
|
* nodes [idx_znode].age = 0;
|
|
*/
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
/* update all znode if it's dirty */
|
|
do_for_all_znodes (&nodes [idx_znode].rc, zi, _cb_update_znode, ZT_ALL);
|
|
|
|
if (nodes [0].flags & ZOF_IF_REFERENCE) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ERASEDESKTOP, 0, (WPARAM)&nodes [idx_znode].rc);
|
|
nodes [0].flags &= ~ZOF_IF_REFERENCE;
|
|
}
|
|
#else /* not defined _MGSCHEMA_COMPOSITING */
|
|
DO_COMPSOR_OP_ARGS (on_dirty_screen,
|
|
get_layer_from_client (cli),
|
|
nodes [idx_znode].flags & ZOF_TYPE_FLAG_MASK,
|
|
&nodes [idx_znode].rc);
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dskMoveWindow (int cli, int idx_znode, HDC memdc, const RECT* rcWin)
|
|
{
|
|
DWORD type;
|
|
int fixed_idx;
|
|
int *first = NULL;
|
|
ZORDERNODE* nodes;
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
unsigned short idx;
|
|
MASKRECT *firstmaskrect;
|
|
int i, slot, nInvCount;
|
|
RECT rcInv[4], rcOld, rcInter, tmprc;
|
|
CLIPRGN bblt_rgn;
|
|
MASKRECT *maskrect;
|
|
#endif
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals) ||
|
|
idx_znode < 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
type = nodes [idx_znode].flags & ZOF_TYPE_MASK;
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
fixed_idx = ZNIDX_SCREENLOCK;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_DOCKER:
|
|
fixed_idx = ZNIDX_DOCKER;
|
|
first = &fixed_idx;
|
|
break;
|
|
case ZOF_TYPE_GLOBAL:
|
|
first = &zi->first_global;
|
|
break;
|
|
case ZOF_TYPE_TOPMOST:
|
|
first = &zi->first_topmost;
|
|
break;
|
|
case ZOF_TYPE_NORMAL:
|
|
first = &zi->first_normal;
|
|
break;
|
|
case ZOF_TYPE_LAUNCHER:
|
|
fixed_idx = ZNIDX_LAUNCHER;
|
|
first = &fixed_idx;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (first == NULL)
|
|
return -1;
|
|
|
|
if (memcmp (&nodes [idx_znode].rc, rcWin, sizeof (RECT)) == 0)
|
|
return 0;
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
if ((RECTW(nodes[idx_znode].rc) != RECTWP(rcWin) ||
|
|
RECTH(nodes[idx_znode].rc) != RECTHP(rcWin)) &&
|
|
(nodes[idx_znode].flags & ZOF_TW_TROUNDCNS ||
|
|
nodes[idx_znode].flags & ZOF_TW_BROUNDCNS)) {
|
|
RECT cli_rect;
|
|
SetRect(&cli_rect, 0, 0, RECTWP(rcWin), RECTHP(rcWin));
|
|
|
|
lock_zi_for_change(zi);
|
|
|
|
if (nodes[idx_znode].idx_mask_rect != 0) {
|
|
|
|
idx = nodes[idx_znode].idx_mask_rect;
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
|
|
while (idx) {
|
|
__mg_slot_clear_use((unsigned char*)GET_MASKRECT_USAGEBMP(zi),
|
|
idx);
|
|
idx = ((MASKRECT *)(firstmaskrect+idx))->next;
|
|
}
|
|
}
|
|
|
|
alloc_mask_rects_for_round_corners (zi, &nodes[idx_znode],
|
|
nodes[idx_znode].flags, &cli_rect);
|
|
|
|
unlock_zi_for_change(zi);
|
|
}
|
|
#endif /* not defined _MGSCHEMA_COMPOSITING */
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE && zi->cli_trackmenu >= 0)
|
|
srvForceCloseMenu (0);
|
|
#endif
|
|
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
nInvCount = SubtractRect (rcInv, &nodes [idx_znode].rc, rcWin);
|
|
|
|
if (nodes [idx_znode].flags & ZOF_VISIBLE) {
|
|
RECT rcScr = GetScreenRect ();
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
if (type > ZOF_TYPE_LAUNCHER) {
|
|
do_for_all_znodes ((void*)rcWin, zi, _cb_intersect_rc, ZT_LAUNCHER);
|
|
}
|
|
if (type > ZOF_TYPE_NORMAL) {
|
|
do_for_all_znodes ((void*)rcWin, zi, _cb_intersect_rc, ZT_NORMAL);
|
|
}
|
|
if (type > ZOF_TYPE_TOPMOST) {
|
|
do_for_all_znodes ((void*)rcWin, zi, _cb_intersect_rc, ZT_TOPMOST);
|
|
}
|
|
if (type > ZOF_TYPE_GLOBAL) {
|
|
do_for_all_znodes ((void*)rcWin, zi, _cb_intersect_rc, ZT_GLOBAL);
|
|
}
|
|
if (type > ZOF_TYPE_DOCKER) {
|
|
do_for_all_znodes ((void*)rcWin, zi, _cb_intersect_rc, ZT_DOCKER);
|
|
}
|
|
|
|
slot = nodes [idx_znode].next;
|
|
for (; slot != 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
DoesIntersect (rcWin, &nodes [slot].rc)) {
|
|
nodes [slot].age++;
|
|
}
|
|
}
|
|
|
|
if (DoesIntersect (rcWin, &rcScr)) {
|
|
nodes [0].age++;
|
|
}
|
|
|
|
/* check influenced zorder nodes */
|
|
//SetClipRgn (&sg_UpdateRgn, rcInv + i);
|
|
SetClipRgn (&sg_UpdateRgn, &(nodes [idx_znode].rc));
|
|
|
|
slot = nodes [idx_znode].next;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
!(nodes [slot].flags & ZOF_IF_REFERENCE) &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_DOCKER) {
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
!(nodes [slot].flags & ZOF_IF_REFERENCE) &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
!(nodes [slot].flags & ZOF_IF_REFERENCE) &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
!(nodes [slot].flags & ZOF_IF_REFERENCE) &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type > ZOF_TYPE_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
!(nodes [slot].flags & ZOF_IF_REFERENCE) &&
|
|
subtract_rgn_by_node(&sg_UpdateRgn, zi, &nodes[slot])) {
|
|
nodes [slot].age++;
|
|
nodes [slot].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(nodes [0].flags & ZOF_IF_REFERENCE) &&
|
|
SubtractClipRect (&sg_UpdateRgn, &rcScr)) {
|
|
nodes [0].age++;
|
|
nodes [0].flags |= ZOF_IF_REFERENCE;
|
|
}
|
|
|
|
rcOld = nodes [idx_znode].rc;
|
|
nodes [idx_znode].rc = *rcWin;
|
|
nodes [idx_znode].age++;
|
|
|
|
#if defined (_MGRM_PROCESSES)
|
|
if (cli == 0 || mgClients [cli].layer == SHAREDRES_TOPMOST_LAYER) {
|
|
#endif
|
|
/* Copy window content to new postion */
|
|
InitClipRgn (&bblt_rgn, &sg_FreeClipRectList);
|
|
if (nodes[idx_znode].idx_mask_rect == 0){
|
|
SelectClipRect (HDC_SCREEN_SYS, rcWin);
|
|
}
|
|
else {
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
idx = nodes [idx_znode].idx_mask_rect;
|
|
|
|
while (idx) {
|
|
maskrect = firstmaskrect + idx;
|
|
SetRect (&tmprc, rcWin->left + maskrect->left,
|
|
rcWin->top + maskrect->top,
|
|
rcWin->left + maskrect->right,
|
|
rcWin->top + maskrect->bottom);
|
|
if ( DoesIntersect (&tmprc, &rcScr)) {
|
|
IntersectRect (&tmprc, &tmprc, &rcScr);
|
|
AddClipRect (&bblt_rgn, &tmprc);
|
|
}
|
|
idx = maskrect->next;
|
|
}
|
|
SelectClipRegion(HDC_SCREEN_SYS, &bblt_rgn);
|
|
}
|
|
|
|
slot = 0;
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
switch (type) {
|
|
case ZOF_TYPE_SCREENLOCK:
|
|
slot = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZOF_TYPE_DOCKER:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_SCREENLOCK);
|
|
slot = ZNIDX_SCREENLOCK;
|
|
break;
|
|
|
|
case ZOF_TYPE_GLOBAL:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_SCREENLOCK);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_DOCKER);
|
|
slot = zi->first_global;
|
|
break;
|
|
|
|
case ZOF_TYPE_TOPMOST:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_SCREENLOCK);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_DOCKER);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_GLOBAL);
|
|
slot = zi->first_topmost;
|
|
break;
|
|
|
|
case ZOF_TYPE_NORMAL:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_SCREENLOCK);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_DOCKER);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_GLOBAL);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_TOPMOST);
|
|
slot = zi->first_normal;
|
|
break;
|
|
|
|
case ZOF_TYPE_LAUNCHER:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_SCREENLOCK);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_DOCKER);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_GLOBAL);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_TOPMOST);
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_NORMAL);
|
|
slot = ZNIDX_LAUNCHER;
|
|
break;
|
|
|
|
case ZOF_TYPE_DESKTOP:
|
|
do_for_all_znodes (NULL, zi, _cb_exclude_rc, ZT_ALL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
while (slot && slot != idx_znode) {
|
|
#if 0
|
|
if (nodes [slot].flags & ZOF_VISIBLE) {
|
|
ExcludeClipRect (HDC_SCREEN_SYS, &nodes [slot].rc);
|
|
}
|
|
#endif
|
|
/* houhh 20090730, if slot window is no regular.*/
|
|
if (nodes [slot].flags & ZOF_VISIBLE) {
|
|
if (nodes[slot].idx_mask_rect == 0) {
|
|
ExcludeClipRect (HDC_SCREEN_SYS, &nodes [slot].rc);
|
|
}
|
|
else {
|
|
RECT rc;
|
|
GetWindowRect(nodes [slot].hwnd, &rc);
|
|
firstmaskrect = GET_MASKRECT(zi);
|
|
idx = nodes [slot].idx_mask_rect;
|
|
while (idx) {
|
|
maskrect = firstmaskrect + idx;
|
|
SetRect (&tmprc, rc.left + maskrect->left,
|
|
rc.top + maskrect->top,
|
|
rc.left + maskrect->right,
|
|
rc.top + maskrect->bottom);
|
|
if ( DoesIntersect (&tmprc, &rcScr)) {
|
|
IntersectRect (&tmprc, &tmprc, &rcScr);
|
|
ExcludeClipRect (HDC_SCREEN_SYS, &tmprc);
|
|
}
|
|
idx = maskrect->next;
|
|
}
|
|
}
|
|
}
|
|
slot = nodes [slot].next;
|
|
}
|
|
BitBlt (HDC_SCREEN_SYS, rcOld.left, rcOld.top,
|
|
MIN (RECTWP (rcWin), RECTW (rcOld)),
|
|
MIN (RECTHP (rcWin), RECTH (rcOld)),
|
|
HDC_SCREEN_SYS, rcWin->left, rcWin->top, 0);
|
|
|
|
/* Restore the clip region of HDC_SCREEN_SYS */
|
|
SelectClipRect (HDC_SCREEN_SYS, &rcScr);
|
|
EmptyClipRgn(&bblt_rgn);
|
|
#if defined (_MGRM_PROCESSES)
|
|
}
|
|
#endif
|
|
|
|
/* unlock zi for change ... */
|
|
unlock_zi_for_change (zi);
|
|
|
|
/* check the invalid rect of the window */
|
|
EmptyClipRgn (&sg_UpdateRgn);
|
|
nInvCount = SubtractRect (rcInv, &rcOld, &rcScr);
|
|
for (i = 0; i < nInvCount; i++) {
|
|
AddClipRect (&sg_UpdateRgn, rcInv + i);
|
|
}
|
|
|
|
/* Since 4.2.0: handle fixed znodes */
|
|
if (type < ZOF_TYPE_SCREENLOCK) {
|
|
slot = ZNIDX_SCREENLOCK;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
|
|
if (type < ZOF_TYPE_DOCKER) {
|
|
slot = ZNIDX_DOCKER;
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
|
|
if (type < ZOF_TYPE_GLOBAL) {
|
|
slot = zi->first_global;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
}
|
|
|
|
if (type < ZOF_TYPE_TOPMOST) {
|
|
slot = zi->first_topmost;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
}
|
|
|
|
if (type < ZOF_TYPE_NORMAL) {
|
|
slot = zi->first_normal;
|
|
for (; slot > 0; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
}
|
|
|
|
slot = *first;
|
|
for (; slot != idx_znode; slot = nodes [slot].next) {
|
|
if (nodes [slot].flags & ZOF_VISIBLE &&
|
|
IntersectRect (&rcInter, &rcOld, &nodes [slot].rc))
|
|
AddClipRect(&sg_UpdateRgn, &rcInter);
|
|
}
|
|
|
|
do_for_all_znodes (&rcOld, zi, _cb_update_znode, ZT_ALL);
|
|
|
|
if (nodes [0].flags & ZOF_IF_REFERENCE) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_ERASEDESKTOP, 0, (LPARAM)&rcOld);
|
|
nodes [0].flags &= ~ZOF_IF_REFERENCE;
|
|
}
|
|
|
|
OffsetRegion (&sg_UpdateRgn,
|
|
rcWin->left - rcOld.left,
|
|
rcWin->top - rcOld.top);
|
|
|
|
update_client_window_rgn (nodes [idx_znode].cli,
|
|
nodes [idx_znode].hwnd);
|
|
}
|
|
else {
|
|
lock_zi_for_change (zi);
|
|
|
|
nodes [idx_znode].rc = *rcWin;
|
|
nodes [idx_znode].age++;
|
|
|
|
unlock_zi_for_change (zi);
|
|
}
|
|
#else /* defined _MGSCHEMA_COMPOSITING */
|
|
{
|
|
RECT org_rc;
|
|
|
|
lock_zi_for_change (zi);
|
|
|
|
org_rc = nodes [idx_znode].rc;
|
|
nodes [idx_znode].rc = *rcWin;
|
|
if (memdc != HDC_INVALID) {
|
|
DeleteMemDC (nodes [idx_znode].mem_dc);
|
|
nodes [idx_znode].mem_dc = memdc;
|
|
}
|
|
|
|
DO_COMPSOR_OP_ARGS (on_moved_win,
|
|
get_layer_from_client (cli), idx_znode, &org_rc);
|
|
|
|
unlock_zi_for_change (zi);
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dskEnableZOrderNode (int cli, int idx_znode, int flags)
|
|
{
|
|
ZORDERINFO* zi = get_zorder_info(cli);
|
|
ZORDERNODE* nodes;
|
|
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals) ||
|
|
idx_znode < 0) {
|
|
return -1;
|
|
}
|
|
|
|
nodes = GET_ZORDERNODE(zi);
|
|
|
|
/* lock zi for change */
|
|
lock_zi_for_change (zi);
|
|
|
|
if (flags) /* enable window */
|
|
nodes [idx_znode].flags &= ~ZOF_DISABLED;
|
|
else
|
|
nodes [idx_znode].flags |= ZOF_DISABLED;
|
|
|
|
/* unlock zi for change */
|
|
unlock_zi_for_change (zi);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*======================== customize desktop =========================*/
|
|
static void
|
|
def_paint_desktop (void* context, HDC dc_desktop, const RECT* inv_rc)
|
|
{
|
|
PBITMAP bg_bmp = NULL;
|
|
int pic_x = 0, pic_y = 0;
|
|
RECT rcScr = GetScreenRect ();
|
|
|
|
if(context)
|
|
{
|
|
bg_bmp = ((DEF_CONTEXT *)context)->bg;
|
|
pic_x = ((DEF_CONTEXT *)context)->x;
|
|
pic_y = ((DEF_CONTEXT *)context)->y;
|
|
}
|
|
|
|
SetBrushColor (dc_desktop,
|
|
GetWindowElementPixelEx (HWND_DESKTOP, HDC_SCREEN, WE_BGC_DESKTOP));
|
|
|
|
if (inv_rc) {
|
|
SelectClipRect (dc_desktop, inv_rc);
|
|
FillBox (dc_desktop, inv_rc->left, inv_rc->top,
|
|
RECTWP (inv_rc), RECTHP (inv_rc));
|
|
}
|
|
else {
|
|
SelectClipRect (dc_desktop, &rcScr);
|
|
FillBox(dc_desktop, rcScr.left, rcScr.top,
|
|
rcScr.right, rcScr.bottom);
|
|
}
|
|
|
|
if (bg_bmp) {
|
|
FillBoxWithBitmap (dc_desktop, pic_x, pic_y,
|
|
bg_bmp->bmWidth, bg_bmp->bmHeight, bg_bmp);
|
|
}
|
|
|
|
}
|
|
|
|
static void def_keyboard_handler(void* context, int message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(message)
|
|
{
|
|
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:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define IDC_DTI_ABOUT (IDM_DTI_FIRST)
|
|
|
|
static void def_customize_desktop_menu (void* context, HMENU hmnu, int start_pos)
|
|
{
|
|
#if defined(_MGMISC_ABOUTDLG) && defined(_MGHAVE_MENU)
|
|
MENUITEMINFO mii;
|
|
|
|
memset (&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.type = MFT_STRING;
|
|
mii.id = IDC_DTI_ABOUT;
|
|
mii.typedata = (DWORD)GetSysText(IDS_MGST_ABOUTMG);
|
|
mii.hsubmenu = 0;
|
|
InsertMenuItem (hmnu, start_pos, TRUE, &mii);
|
|
#endif
|
|
}
|
|
|
|
static void def_mouse_handler(void* context, int message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#ifdef _MGHAVE_MENU
|
|
int x, y;
|
|
switch(message)
|
|
{
|
|
case MSG_DT_LBUTTONDOWN:
|
|
case MSG_DT_LBUTTONUP:
|
|
case MSG_DT_LBUTTONDBLCLK:
|
|
case MSG_DT_MOUSEMOVE:
|
|
case MSG_DT_RBUTTONDOWN:
|
|
case MSG_DT_RBUTTONDBLCLK:
|
|
break;
|
|
|
|
case MSG_DT_RBUTTONUP:
|
|
{
|
|
x = LOSWORD (lParam);
|
|
y = HISWORD (lParam);
|
|
|
|
TrackPopupMenu (sg_DesktopMenu, TPM_DEFAULT, x, y, HWND_DESKTOP);
|
|
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void def_desktop_menucmd_handler (void* context, int id)
|
|
{
|
|
#ifdef _MGMISC_ABOUTDLG
|
|
if (id == IDC_DTI_ABOUT) {
|
|
#ifdef _MGRM_THREADS
|
|
OpenAboutDialog ();
|
|
#else
|
|
OpenAboutDialog (HWND_DESKTOP);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void def_deinit(void* context)
|
|
{
|
|
if(context) {
|
|
if (((DEF_CONTEXT *)context)->bg)
|
|
UnloadBitmap (((DEF_CONTEXT *)context)->bg);
|
|
|
|
#if defined(_MGRM_THREADS) || defined(_MGRM_STANDALONE)
|
|
free(context);
|
|
#endif
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int dskGetBgPicturePos (void)
|
|
{
|
|
char szValue [21];
|
|
|
|
if(GetMgEtcValue (__mg_def_renderer->name,
|
|
SYSBMP_BGPICPOS, szValue, 20) < 0) {
|
|
strcpy (szValue, "center");
|
|
}
|
|
|
|
if (!strcmp (szValue, "none"))
|
|
return -1;
|
|
if (!strcmp (szValue, "center"))
|
|
return 0;
|
|
if (!strcmp (szValue, "upleft"))
|
|
return 1;
|
|
if (!strcmp (szValue, "downleft"))
|
|
return 2;
|
|
if (!strcmp (szValue, "upright"))
|
|
return 3;
|
|
if (!strcmp (szValue, "downright"))
|
|
return 4;
|
|
if (!strcmp (szValue, "upcenter"))
|
|
return 5;
|
|
if (!strcmp (szValue, "downcenter"))
|
|
return 6;
|
|
if (!strcmp (szValue, "vcenterleft"))
|
|
return 7;
|
|
if (!strcmp (szValue, "vcenterright"))
|
|
return 8;
|
|
|
|
return -1;
|
|
}
|
|
|
|
static PBITMAP dskLoadBgPicture (void)
|
|
{
|
|
return (PBITMAP)GetSystemBitmapEx (__mg_def_renderer->name,
|
|
SYSBMP_BGPICTURE);
|
|
}
|
|
|
|
static void dskGetBgPictureXY (int pos, int w, int h, int* x, int* y)
|
|
{
|
|
switch (pos) {
|
|
case 0: // center
|
|
*x = (g_rcScr.right - w) >> 1;
|
|
*y = (g_rcScr.bottom - h) >> 1;
|
|
break;
|
|
case 1: // upleft
|
|
*x = 0;
|
|
*y = 0;
|
|
break;
|
|
case 2: // downleft
|
|
*x = 0;
|
|
*y = g_rcScr.bottom - h;
|
|
break;
|
|
case 3: // upright
|
|
*x = g_rcScr.right - w;
|
|
*y = 0;
|
|
break;
|
|
case 4: // downright
|
|
*x = g_rcScr.right - w;
|
|
*y = g_rcScr.bottom - h;
|
|
break;
|
|
case 5: // upcenter
|
|
*x = (g_rcScr.right - w) >> 1;
|
|
*y = 0;
|
|
break;
|
|
case 6: // downcenter
|
|
*x = (g_rcScr.right - w) >> 1;
|
|
*y = g_rcScr.bottom - h;
|
|
break;
|
|
case 7: // vcenterleft
|
|
*x = 0;
|
|
*y = (g_rcScr.bottom - h) >> 1;
|
|
break;
|
|
case 8: // vcenterright
|
|
*x = g_rcScr.right - w;
|
|
*y = (g_rcScr.bottom - h) >> 1;
|
|
break;
|
|
default:
|
|
*x = 0;
|
|
*y = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void* def_init(void)
|
|
{
|
|
PBITMAP bg_bmp = NULL;
|
|
int pic_x = 0, pic_y = 0;
|
|
DEF_CONTEXT *con;
|
|
int pos;
|
|
|
|
#if defined (_MGRM_THREADS) || defined (_MGRM_STANDALONE)
|
|
con = malloc(sizeof(DEF_CONTEXT));
|
|
#else
|
|
con = &g_def_context;
|
|
#endif
|
|
|
|
pos = dskGetBgPicturePos ();
|
|
if (pos < 0)
|
|
bg_bmp = NULL;
|
|
else
|
|
bg_bmp = dskLoadBgPicture ();
|
|
|
|
if (bg_bmp)
|
|
dskGetBgPictureXY (pos,
|
|
bg_bmp->bmWidth, bg_bmp->bmHeight, &pic_x, &pic_y);
|
|
|
|
con->bg = bg_bmp;
|
|
con->x = pic_x;
|
|
con->y = pic_y;
|
|
|
|
return (void *)con;
|
|
}
|
|
|
|
static DESKTOPOPS def_dsk_ops =
|
|
{
|
|
def_init,
|
|
def_deinit,
|
|
def_paint_desktop,
|
|
def_keyboard_handler,
|
|
def_mouse_handler,
|
|
def_customize_desktop_menu,
|
|
def_desktop_menucmd_handler,
|
|
};
|
|
|
|
static DESKTOPOPS *dsk_ops = &def_dsk_ops;
|
|
static void *dt_context;
|
|
|
|
DESKTOPOPS* GUIAPI SetCustomDesktopOperationSet (DESKTOPOPS* usr_dsk_ops)
|
|
{
|
|
DESKTOPOPS *tmp_ops = NULL;
|
|
|
|
if (usr_dsk_ops == NULL) {
|
|
return dsk_ops;
|
|
}
|
|
|
|
if (dsk_ops->deinit) {
|
|
dsk_ops->deinit(dt_context);
|
|
}
|
|
|
|
if (usr_dsk_ops->init) {
|
|
dt_context = usr_dsk_ops->init();
|
|
}
|
|
|
|
tmp_ops = dsk_ops;
|
|
dsk_ops = usr_dsk_ops;
|
|
|
|
SendMessage(HWND_DESKTOP, MSG_ERASEDESKTOP, 0, 0);
|
|
|
|
return tmp_ops;
|
|
}
|
|
|
|
static BOOL _cb_bcast_msg (void* context,
|
|
const ZORDERINFO* zi, ZORDERNODE* node)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMSG pMsg = (PMSG)context;
|
|
|
|
#if defined(_MGRM_PROCESSES)
|
|
if (node->cli == __mg_client_id) {
|
|
#endif
|
|
pWin = (PMAINWIN)node->hwnd;
|
|
if (pWin && pWin->WinType != TYPE_CONTROL) {
|
|
PostMessage ((HWND)pWin, pMsg->message, pMsg->wParam, pMsg->lParam);
|
|
return TRUE;
|
|
}
|
|
#if defined(_MGRM_PROCESSES)
|
|
}
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int dskBroadcastMessage (PMSG pMsg)
|
|
{
|
|
int count = 0;
|
|
|
|
lock_zi_for_read (__mg_zorder_info);
|
|
count = do_for_all_znodes (pMsg, __mg_zorder_info, _cb_bcast_msg, ZT_ALL);
|
|
unlock_zi_for_read (__mg_zorder_info);
|
|
|
|
return count;
|
|
}
|
|
|
|
static int dskSetIMEStatus (int iIMEStatusCode, int Value)
|
|
{
|
|
if (__mg_ime_wnd == 0)
|
|
return ERR_IME_NOIMEWND;
|
|
|
|
switch (iIMEStatusCode) {
|
|
case IME_STATUS_REGISTERED:
|
|
return 0;
|
|
|
|
case IME_STATUS_ENABLED:
|
|
__mg_ime_status_info.bEnabled = Value;
|
|
SendNotifyMessage (__mg_ime_wnd,
|
|
Value == 1? MSG_IME_OPEN : MSG_IME_CLOSE,
|
|
0, 0);
|
|
return 0;
|
|
|
|
case IME_STATUS_AUTOTRACK:
|
|
__mg_ime_status_info.bAutoTrack = Value;
|
|
return 0;
|
|
|
|
case IME_STATUS_LANGUAGE:
|
|
case IME_STATUS_ENCODING:
|
|
return SendMessage (__mg_ime_wnd,
|
|
MSG_IME_SETSTATUS, iIMEStatusCode, Value);
|
|
|
|
default:
|
|
if (iIMEStatusCode >= IME_STATUS_USER_MIN
|
|
&& iIMEStatusCode <= IME_STATUS_USER_MAX)
|
|
return SendMessage (__mg_ime_wnd,
|
|
MSG_IME_SETSTATUS, iIMEStatusCode, Value);
|
|
}
|
|
|
|
return ERR_NO_MATCH;
|
|
}
|
|
|
|
static int dskGetIMEStatus (int iIMEStatusCode)
|
|
{
|
|
if (__mg_ime_wnd == 0) {
|
|
if (iIMEStatusCode == IME_STATUS_REGISTERED)
|
|
return 0;
|
|
else
|
|
return ERR_IME_NOIMEWND;
|
|
}
|
|
|
|
switch (iIMEStatusCode) {
|
|
case IME_STATUS_REGISTERED:
|
|
return 1;
|
|
|
|
case IME_STATUS_ENABLED:
|
|
return __mg_ime_status_info.bEnabled;
|
|
|
|
case IME_STATUS_AUTOTRACK:
|
|
return __mg_ime_status_info.bAutoTrack;
|
|
|
|
case IME_STATUS_LANGUAGE:
|
|
case IME_STATUS_ENCODING:
|
|
case IME_STATUS_VERSION:
|
|
return SendMessage (__mg_ime_wnd,
|
|
MSG_IME_GETSTATUS, iIMEStatusCode, 0);
|
|
|
|
default:
|
|
if (iIMEStatusCode >= IME_STATUS_USER_MIN
|
|
&& iIMEStatusCode <= IME_STATUS_USER_MAX)
|
|
return SendMessage (__mg_ime_wnd,
|
|
MSG_IME_GETSTATUS, iIMEStatusCode, 0);
|
|
}
|
|
|
|
return ERR_NO_MATCH;
|
|
}
|
|
|
|
static int dskSetIMETargetInfo (const IME_TARGET_INFO *info)
|
|
{
|
|
if (__mg_ime_wnd == 0)
|
|
return ERR_IME_NOIMEWND;
|
|
|
|
memcpy (&__mg_ime_status_info.TargetInfo, info, sizeof (IME_TARGET_INFO));
|
|
|
|
if (__mg_ime_status_info.bAutoTrack) {
|
|
int ret;
|
|
ret = dskGetIMEStatus (IME_STATUS_VERSION);
|
|
if (ret) {
|
|
PostMessage (__mg_ime_wnd, MSG_IME_SET_TARGET_INFO,
|
|
0, (LPARAM)&__mg_ime_status_info.TargetInfo);
|
|
} else {
|
|
PostMessage (__mg_ime_wnd, MSG_IME_SETPOS,
|
|
0, (LPARAM)&__mg_ime_status_info.TargetInfo.ptCaret);
|
|
}
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static int dskGetIMETargetInfo (IME_TARGET_INFO *info)
|
|
{
|
|
if (__mg_ime_wnd == 0)
|
|
return ERR_IME_NOIMEWND;
|
|
|
|
*info = __mg_ime_status_info.TargetInfo;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
#ifdef _DEB
|
|
void GUIAPI DumpWindow (FILE* fp, HWND hWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
PCONTROL pCtrl;
|
|
|
|
if (pWin->DataType != TYPE_HWND) {
|
|
fprintf (fp, "DumpWindow: Invalid DataType!\n");
|
|
return;
|
|
}
|
|
|
|
if (pWin->WinType == TYPE_MAINWIN) {
|
|
fprintf (fp, "=============== Main Window %#x==================\n",
|
|
hWnd);
|
|
|
|
fprintf (fp, "Rect -- (%d, %d, %d, %d)\n",
|
|
pWin->left, pWin->top, pWin->right, pWin->bottom);
|
|
fprintf (fp, "Client -- (%d, %d, %d, %d)\n",
|
|
pWin->cl, pWin->ct, pWin->cr, pWin->cb);
|
|
|
|
fprintf (fp, "Style -- %lx\n", pWin->dwStyle);
|
|
fprintf (fp, "ExStyle -- %lx\n", pWin->dwExStyle);
|
|
|
|
//fprintf (fp, "PrivDC -- %#x\n", pWin->privDC);
|
|
|
|
fprintf (fp, "AddData -- %lx\n", pWin->dwAddData);
|
|
fprintf (fp, "AddData2 -- %lx\n", pWin->dwAddData2);
|
|
|
|
fprintf (fp, "WinProc -- %p\n", pWin->MainWindowProc);
|
|
|
|
fprintf (fp, "Caption -- %s\n", pWin->spCaption);
|
|
fprintf (fp, "ID -- %d\n", pWin->id);
|
|
|
|
fprintf (fp, "FirstChild -- %#x\n", pWin->hFirstChild);
|
|
pCtrl = (PCONTROL)pWin->hFirstChild;
|
|
while (pCtrl) {
|
|
fprintf (fp, " Child -- %p(%d), %s(%d)\n", pCtrl, pCtrl->id,
|
|
pCtrl->pcci->name, pCtrl->pcci->nUseCount);
|
|
pCtrl = pCtrl->next;
|
|
}
|
|
fprintf (fp, "ActiveChild -- %#x\n", pWin->hActiveChild);
|
|
|
|
fprintf (fp, "Hosting -- %p\n", pWin->pHosting);
|
|
fprintf (fp, "FirstHosted -- %p\n", pWin->pFirstHosted);
|
|
fprintf (fp, "NextHosted -- %p\n", pWin->pNextHosted);
|
|
fprintf (fp, "BkColor -- %d\n", pWin->iBkColor);
|
|
fprintf (fp, "Menu -- %#x\n", pWin->hMenu);
|
|
fprintf (fp, "Accel -- %#x\n", pWin->hAccel);
|
|
fprintf (fp, "Cursor -- %#x\n", pWin->hCursor);
|
|
fprintf (fp, "Icon -- %#x\n", pWin->hIcon);
|
|
fprintf (fp, "SysMenu -- %#x\n", pWin->hSysMenu);
|
|
fprintf (fp, "MsgQueue -- %p\n", pWin->pMessages);
|
|
}
|
|
else {
|
|
fprintf (fp, "=============== Control %#x==================\n", hWnd);
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
fprintf (fp, "Rect -- (%d, %d, %d, %d)\n",
|
|
pCtrl->left, pCtrl->top, pCtrl->right, pCtrl->bottom);
|
|
fprintf (fp, "Client -- (%d, %d, %d, %d)\n",
|
|
pCtrl->cl, pCtrl->ct, pCtrl->cr, pCtrl->cb);
|
|
|
|
fprintf (fp, "Style -- %lx\n", pCtrl->dwStyle);
|
|
fprintf (fp, "ExStyle -- %lx\n", pCtrl->dwExStyle);
|
|
|
|
fprintf (fp, "PrivCDC -- %#x\n", pCtrl->privCDC);
|
|
|
|
fprintf (fp, "AddData -- %lx\n", pCtrl->dwAddData);
|
|
fprintf (fp, "AddData2 -- %lx\n", pCtrl->dwAddData2);
|
|
|
|
fprintf (fp, "WinProc -- %p\n", pCtrl->ControlProc);
|
|
|
|
fprintf (fp, "Caption -- %s\n", pCtrl->spCaption);
|
|
fprintf (fp, "ID -- %d\n", pCtrl->id);
|
|
|
|
fprintf (fp, "FirstChild -- %p\n", pCtrl->children);
|
|
fprintf (fp, "ActiveChild -- %p\n", pCtrl->active);
|
|
fprintf (fp, "Parent -- %p\n", pCtrl->pParent);
|
|
fprintf (fp, "Next -- %p\n", pCtrl->next);
|
|
|
|
pCtrl = (PCONTROL)pCtrl->children;
|
|
while (pCtrl) {
|
|
fprintf (fp, " Child -- %p(%d), %s(%d)\n", pCtrl, pCtrl->id,
|
|
pCtrl->pcci->name, pCtrl->pcci->nUseCount);
|
|
pCtrl = pCtrl->next;
|
|
}
|
|
}
|
|
|
|
fprintf (fp, "=================== End ==================\n");
|
|
return;
|
|
}
|
|
#endif /* _DEBUG */
|
|
|
|
int __kernel_get_window_region (HWND pWin, CLIPRGN* region)
|
|
{
|
|
RECT rc;
|
|
MASKRECT *maskrect;
|
|
ZORDERNODE* nodes;
|
|
ZORDERINFO* zi;
|
|
int idx_znode, idx, nr_mask_rects;
|
|
|
|
#if defined(_MGRM_THREADS) || defined(_MGRM_STANDALONE)
|
|
zi = get_zorder_info (0);
|
|
#else
|
|
zi = get_zorder_info (__mg_client_id);
|
|
#endif
|
|
|
|
idx_znode = ((PMAINWIN)pWin)->idx_znode;
|
|
if (idx_znode > (zi->max_nr_globals
|
|
+ zi->max_nr_topmosts + zi->max_nr_normals)
|
|
|| idx_znode <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
EmptyClipRgn (region);
|
|
|
|
/* lock zi for read */
|
|
lock_zi_for_read (zi);
|
|
|
|
nr_mask_rects = 0;
|
|
nodes = GET_ZORDERNODE(zi);
|
|
maskrect = GET_MASKRECT(zi);
|
|
idx = nodes[idx_znode].idx_mask_rect;
|
|
while (idx) {
|
|
rc.left = maskrect->left;
|
|
rc.top = maskrect->top;
|
|
rc.right = maskrect->left;
|
|
rc.bottom = maskrect->bottom;
|
|
|
|
if (!AddClipRect (region, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
|
|
idx = maskrect->next;
|
|
nr_mask_rects ++;
|
|
}
|
|
|
|
if (nr_mask_rects == 0) {
|
|
rc = nodes [idx_znode].rc;
|
|
/* VW: 2020-02-02: bad call to `OffsetRect (&rc, rc.left, rc.top);` */
|
|
OffsetRect (&rc, -rc.left, -rc.top);
|
|
if (!SetClipRgn (region, &rc))
|
|
nr_mask_rects = -1;
|
|
}
|
|
|
|
err_ret:
|
|
/* unlock zi for read */
|
|
unlock_zi_for_read (zi);
|
|
|
|
return nr_mask_rects;
|
|
}
|
|
|
|
#ifdef _MGRM_PROCESSES
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
struct _my_circle_context {
|
|
int status; /* whether failed to allocate cliprect for region */
|
|
int r; /* the radius of the round corner */
|
|
RECT rc; /* the rectangle of the znode */
|
|
DWORD tw_flags; /* the corner flags of the znode */
|
|
DWORD rgn_ops; /* region operation */
|
|
CLIPRGN* dst_rgn; /* the destination region */
|
|
};
|
|
|
|
static void cb_circle_corners (void* context, int x1, int x2, int y)
|
|
{
|
|
struct _my_circle_context* ctxt = (struct _my_circle_context*)context;
|
|
RECT rc;
|
|
|
|
if (ctxt->status) // check status first
|
|
return;
|
|
|
|
if (y < 0) {
|
|
if (ctxt->tw_flags & ZOF_TW_TROUNDCNS) {
|
|
rc.left = ctxt->rc.left + x1 + ctxt->r;
|
|
rc.right = ctxt->rc.right + x2 - ctxt->r;
|
|
rc.top = ctxt->rc.top + y + ctxt->r;
|
|
rc.bottom = rc.top + 1;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
else if (y > 0) {
|
|
if (ctxt->tw_flags & ZOF_TW_BROUNDCNS) {
|
|
rc.left = ctxt->rc.left + x1 + ctxt->r;
|
|
rc.right = ctxt->rc.right + x2 - ctxt->r;
|
|
rc.top = ctxt->rc.bottom + y - ctxt->r;
|
|
rc.bottom = rc.top + 1;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
rc.left = ctxt->rc.left + x1 + ctxt->r;
|
|
rc.right = ctxt->rc.right + x2 - ctxt->r;
|
|
rc.top = ctxt->rc.bottom - ctxt->r;
|
|
rc.bottom = rc.top + 1;
|
|
}
|
|
|
|
// check out of bound
|
|
{
|
|
RECT eff_rc = ctxt->rc;
|
|
if (!IntersectRect (&rc, &eff_rc, &rc))
|
|
return;
|
|
}
|
|
|
|
if (!(ctxt->rgn_ops & RGN_OP_FLAG_ABS)) {
|
|
OffsetRect (&rc, -ctxt->rc.left, -ctxt->rc.top);
|
|
}
|
|
|
|
if ((ctxt->rgn_ops & RGN_OP_MASK) == RGN_OP_EXCLUDE) {
|
|
if (!SubtractClipRect (ctxt->dst_rgn, &rc))
|
|
ctxt->status = -1;
|
|
}
|
|
else {
|
|
_DBG_PRINTF("add new rect: %d, %d, %d, %d for (%d, %d) to (%d, %d)\n",
|
|
rc.left, rc.top, rc.right, rc.bottom, x1, y, x2, y);
|
|
if (!AddClipRect (ctxt->dst_rgn, &rc))
|
|
ctxt->status = -1;
|
|
}
|
|
}
|
|
#endif /* _MGSCHEMA_COMPOSITING */
|
|
|
|
|
|
BOOL GUIAPI ServerGetWinZNodeRegion (MG_Layer* layer, int idx_znode,
|
|
DWORD rgn_ops, CLIPRGN* dst_rgn)
|
|
{
|
|
RECT rc;
|
|
MASKRECT *maskrect;
|
|
ZORDERNODE* nodes;
|
|
ZORDERINFO* zi;
|
|
int idx, nr_mask_rects;
|
|
|
|
if (!mgIsServer || idx_znode <= 0)
|
|
return FALSE;
|
|
|
|
if (layer) {
|
|
zi = mgTopmostLayer->zorder_info;
|
|
}
|
|
else {
|
|
if (!__mg_is_valid_layer (layer))
|
|
return FALSE;
|
|
zi = layer->zorder_info;
|
|
}
|
|
|
|
if (idx_znode > (zi->max_nr_globals +
|
|
zi->max_nr_topmosts + zi->max_nr_normals)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((rgn_ops & RGN_OP_MASK) == RGN_OP_SET) {
|
|
EmptyClipRgn (dst_rgn);
|
|
rgn_ops &= ~RGN_OP_MASK;
|
|
rgn_ops |= RGN_OP_INCLUDE;
|
|
}
|
|
|
|
/* lock zi for read */
|
|
lock_zi_for_read (zi);
|
|
|
|
nr_mask_rects = 0;
|
|
nodes = GET_ZORDERNODE(zi);
|
|
maskrect = GET_MASKRECT(zi);
|
|
idx = nodes [idx_znode].idx_mask_rect;
|
|
while (idx) {
|
|
rc.left = maskrect->left;
|
|
rc.top = maskrect->top;
|
|
rc.right = maskrect->left;
|
|
rc.bottom = maskrect->bottom;
|
|
|
|
if (rgn_ops & RGN_OP_FLAG_ABS) {
|
|
OffsetRect (&rc, nodes[idx_znode].rc.left, nodes[idx_znode].rc.top);
|
|
}
|
|
|
|
if ((rgn_ops & RGN_OP_MASK) == RGN_OP_EXCLUDE) {
|
|
if (!SubtractClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
else {
|
|
if (!AddClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
|
|
idx = maskrect->next;
|
|
nr_mask_rects ++;
|
|
}
|
|
|
|
if (nr_mask_rects == 0) {
|
|
rc = nodes[idx_znode].rc;
|
|
if (!(rgn_ops & RGN_OP_FLAG_ABS)) {
|
|
OffsetRect (&rc, -rc.left, -rc.top);
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
/* Since 4.2.0, we count in the round corners here */
|
|
if (nodes[idx_znode].flags & ZOF_TW_FLAG_MASK) {
|
|
struct _my_circle_context ctxt = { 0, RADIUS_WINDOW_CORNERS, };
|
|
|
|
if (RECTW(rc) >= (RADIUS_WINDOW_CORNERS << 1) &&
|
|
RECTH(rc) >= (RADIUS_WINDOW_CORNERS << 1)) {
|
|
ctxt.status = 0;
|
|
ctxt.r = RADIUS_WINDOW_CORNERS;
|
|
ctxt.rc = rc;
|
|
/* both top and bottom corners for popup menu */
|
|
ctxt.tw_flags = nodes[idx_znode].flags & ZOF_TW_FLAG_MASK;
|
|
ctxt.rgn_ops = rgn_ops;
|
|
ctxt.dst_rgn = dst_rgn;
|
|
|
|
CircleGenerator (&ctxt, 0, 0, RADIUS_WINDOW_CORNERS,
|
|
cb_circle_corners);
|
|
|
|
if (ctxt.status) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
|
|
if (nodes[idx_znode].flags & ZOF_TW_TROUNDCNS) {
|
|
rc.top += RADIUS_WINDOW_CORNERS;
|
|
}
|
|
if (nodes[idx_znode].flags & ZOF_TW_BROUNDCNS) {
|
|
rc.bottom -= RADIUS_WINDOW_CORNERS;
|
|
}
|
|
}
|
|
}
|
|
#endif /* _MGSCHEMA_COMPOSITING */
|
|
|
|
if ((rgn_ops & RGN_OP_MASK) == RGN_OP_EXCLUDE) {
|
|
if (!SubtractClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
else {
|
|
if (!AddClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
err_ret:
|
|
/* unlock zi for read */
|
|
unlock_zi_for_read (zi);
|
|
|
|
return nr_mask_rects >= 0;
|
|
}
|
|
|
|
BOOL GUIAPI ServerGetPopupMenuZNodeRegion (int idx_znode,
|
|
DWORD rgn_ops, CLIPRGN* dst_rgn)
|
|
{
|
|
RECT rc;
|
|
ZORDERNODE* nodes;
|
|
ZORDERINFO* zi;
|
|
int nr_mask_rects = 0;
|
|
|
|
if (!mgIsServer || idx_znode < 0)
|
|
return FALSE;
|
|
|
|
zi = mgTopmostLayer->zorder_info;
|
|
if (idx_znode >= zi->nr_popupmenus)
|
|
return FALSE;
|
|
|
|
if ((rgn_ops & RGN_OP_MASK) == RGN_OP_SET) {
|
|
EmptyClipRgn (dst_rgn);
|
|
rgn_ops &= ~RGN_OP_MASK;
|
|
rgn_ops |= RGN_OP_INCLUDE;
|
|
}
|
|
|
|
/* lock zi for read */
|
|
lock_zi_for_read (zi);
|
|
|
|
nodes = GET_MENUNODE(zi);
|
|
rc = nodes[idx_znode].rc;
|
|
if (!(rgn_ops & RGN_OP_FLAG_ABS)) {
|
|
OffsetRect (&rc, -rc.left, -rc.top);
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
{
|
|
struct _my_circle_context ctxt = { 0, RADIUS_POPUPMENU_CORNERS, };
|
|
|
|
if (RECTW(rc) >= (RADIUS_POPUPMENU_CORNERS << 1) &&
|
|
RECTH(rc) >= (RADIUS_POPUPMENU_CORNERS << 1)) {
|
|
ctxt.status = 0;
|
|
ctxt.r = RADIUS_POPUPMENU_CORNERS;
|
|
ctxt.rc = rc;
|
|
/* both top and bottom corners for popup menu */
|
|
ctxt.tw_flags = ZOF_TW_TROUNDCNS | ZOF_TW_BROUNDCNS;
|
|
ctxt.rgn_ops = rgn_ops;
|
|
ctxt.dst_rgn = dst_rgn;
|
|
|
|
CircleGenerator (&ctxt, 0, 0, RADIUS_POPUPMENU_CORNERS,
|
|
cb_circle_corners);
|
|
|
|
if (ctxt.status) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
|
|
rc.top += RADIUS_POPUPMENU_CORNERS;
|
|
rc.bottom -= RADIUS_POPUPMENU_CORNERS;
|
|
}
|
|
}
|
|
#endif /* _MGSCHEMA_COMPOSITING */
|
|
|
|
if ((rgn_ops & RGN_OP_MASK) == RGN_OP_EXCLUDE) {
|
|
if (!SubtractClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
else {
|
|
if (!AddClipRect (dst_rgn, &rc)) {
|
|
nr_mask_rects = -1;
|
|
goto err_ret;
|
|
}
|
|
}
|
|
|
|
err_ret:
|
|
/* unlock zi for read */
|
|
unlock_zi_for_read (zi);
|
|
|
|
return nr_mask_rects >= 0;
|
|
}
|
|
|
|
#endif /* _MGRM_PROCESSES */
|
|
|