Removed next and child fields in the window structure and use
WIN_ListChildren instead.
This commit is contained in:
parent
d30d2d8efc
commit
80593bf842
|
@ -175,28 +175,36 @@ fail:
|
|||
* adding to the clip region the intersection of the target rectangle
|
||||
* with an offset window rectangle.
|
||||
*/
|
||||
static BOOL DCE_AddClipRects( HWND start, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
|
||||
static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
|
||||
{
|
||||
RECT rect;
|
||||
WND *pWnd;
|
||||
int i;
|
||||
HWND *list = WIN_ListChildren( parent );
|
||||
|
||||
for (pWnd = WIN_FindWndPtr(start); (pWnd && (pWnd->hwndSelf != end)); WIN_UpdateWndPtr(&pWnd,pWnd->next))
|
||||
if (!list) return;
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
if( !(pWnd->dwStyle & WS_VISIBLE) ) continue;
|
||||
|
||||
rect.left = pWnd->rectWindow.left + x;
|
||||
rect.top = pWnd->rectWindow.top + y;
|
||||
rect.right = pWnd->rectWindow.right + x;
|
||||
rect.bottom = pWnd->rectWindow.bottom + y;
|
||||
|
||||
if( IntersectRect( &rect, &rect, lpRect ))
|
||||
if (list[i] == end) break;
|
||||
if (!(pWnd = WIN_FindWndPtr( list[i] ))) continue;
|
||||
if (pWnd->dwStyle & WS_VISIBLE)
|
||||
{
|
||||
if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
|
||||
rect.left = pWnd->rectWindow.left + x;
|
||||
rect.top = pWnd->rectWindow.top + y;
|
||||
rect.right = pWnd->rectWindow.right + x;
|
||||
rect.bottom = pWnd->rectWindow.bottom + y;
|
||||
if( IntersectRect( &rect, &rect, lpRect ))
|
||||
{
|
||||
if(!REGION_UnionRectWithRgn( hrgnClip, &rect ))
|
||||
{
|
||||
WIN_ReleaseWndPtr( pWnd );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WIN_ReleaseWndPtr( pWnd );
|
||||
}
|
||||
start = pWnd->hwndSelf;
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
return (start == end);
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
|
||||
|
@ -230,7 +238,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
* DCE_GetVisRect() returns a rectangle either in client
|
||||
* or in window coordinates (for DCX_WINDOW request). */
|
||||
|
||||
if( (flags & DCX_CLIPCHILDREN) && wndPtr->child )
|
||||
if (flags & DCX_CLIPCHILDREN)
|
||||
{
|
||||
if( flags & DCX_WINDOW )
|
||||
{
|
||||
|
@ -243,7 +251,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
else
|
||||
xoffset = yoffset = 0;
|
||||
|
||||
DCE_AddClipRects( wndPtr->child->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
|
||||
DCE_AddClipRects( wndPtr->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
|
||||
}
|
||||
|
||||
/* We may need to clip children of child window, if a window with PARENTDC
|
||||
|
@ -251,7 +259,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
* preference dialogs) gets here, we take the region for the parent window
|
||||
* but apparently still need to clip the children of the child window... */
|
||||
|
||||
if( (cflags & DCX_CLIPCHILDREN) && childWnd && childWnd->child )
|
||||
if( (cflags & DCX_CLIPCHILDREN) && childWnd)
|
||||
{
|
||||
if( flags & DCX_WINDOW )
|
||||
{
|
||||
|
@ -268,7 +276,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
xoffset += childWnd->rectClient.left;
|
||||
yoffset += childWnd->rectClient.top;
|
||||
|
||||
DCE_AddClipRects( childWnd->child->hwndSelf, 0, hrgnClip,
|
||||
DCE_AddClipRects( childWnd->hwndSelf, 0, hrgnClip,
|
||||
&rect, xoffset, yoffset );
|
||||
}
|
||||
|
||||
|
@ -287,8 +295,8 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
}
|
||||
|
||||
if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
|
||||
DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
|
||||
wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
|
||||
DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
|
||||
hrgnClip, &rect, xoffset, yoffset );
|
||||
|
||||
/* Clip siblings of all ancestors that have the
|
||||
* WS_CLIPSIBLINGS style
|
||||
|
@ -303,8 +311,8 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
|||
yoffset -= wndPtr->rectClient.top;
|
||||
if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
|
||||
{
|
||||
DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
|
||||
wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
|
||||
DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
|
||||
hrgnClip, &rect, xoffset, yoffset );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,7 +509,8 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
|
|||
/* don't need to change the Zorder of hwnd if it's already inserted
|
||||
* after hwndInsertAfter or when inserting hwnd after itself.
|
||||
*/
|
||||
if(( wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
|
||||
if ((winpos->hwnd == winpos->hwndInsertAfter) ||
|
||||
(winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
|
||||
winpos->flags |= SWP_NOZORDER;
|
||||
}
|
||||
WIN_ReleaseWndPtr(wnd);
|
||||
|
@ -543,7 +552,10 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
|
|||
}
|
||||
else
|
||||
if( winpos->hwndInsertAfter == HWND_BOTTOM )
|
||||
winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
|
||||
{
|
||||
if (!GetWindow( wndPtr->hwndSelf, GW_HWNDNEXT ))
|
||||
winpos->flags |= SWP_NOZORDER;
|
||||
}
|
||||
else
|
||||
if( !(winpos->flags & SWP_NOZORDER) )
|
||||
if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
|
||||
|
|
|
@ -144,12 +144,14 @@ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
|
|||
RECT rc, cliprc;
|
||||
WND* wnd = WIN_FindWndPtr( hwnd );
|
||||
|
||||
if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE ))
|
||||
if (!wnd) return ERROR;
|
||||
if (!WIN_IsWindowDrawable( wnd, TRUE ))
|
||||
{
|
||||
retVal = ERROR;
|
||||
goto END;
|
||||
WIN_ReleaseWndPtr( wnd );
|
||||
return ERROR;
|
||||
}
|
||||
hwnd = wnd->hwndSelf; /* make it a full handle */
|
||||
WIN_ReleaseWndPtr( wnd );
|
||||
|
||||
GetClientRect(hwnd, &rc);
|
||||
if (rect) IntersectRect(&rc, &rc, rect);
|
||||
|
@ -203,16 +205,22 @@ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
|
|||
|
||||
if( flags & SW_SCROLLCHILDREN )
|
||||
{
|
||||
RECT r;
|
||||
WND *w;
|
||||
for( w =WIN_LockWndPtr(wnd->child); w; WIN_UpdateWndPtr(&w, w->next))
|
||||
HWND *list = WIN_ListChildren( hwnd );
|
||||
|
||||
if (list)
|
||||
{
|
||||
r = w->rectWindow;
|
||||
if( !rect || IntersectRect(&r, &r, &rc) )
|
||||
SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
|
||||
w->rectWindow.top + dy, 0,0, SWP_NOZORDER |
|
||||
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
|
||||
SWP_DEFERERASE );
|
||||
int i;
|
||||
RECT r, dummy;
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
GetWindowRect( list[i], &r );
|
||||
MapWindowPoints( 0, hwnd, (POINT *)&r, 2 );
|
||||
if (!rect || IntersectRect(&dummy, &r, &rc))
|
||||
SetWindowPos( list[i], 0, r.left + dx, r.top + dy, 0, 0,
|
||||
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
|
||||
SWP_NOREDRAW | SWP_DEFERERASE );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +238,5 @@ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
|
|||
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
|
||||
DeleteObject( hrgnClip );
|
||||
}
|
||||
END:
|
||||
WIN_ReleaseWndPtr(wnd);
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -707,7 +707,8 @@ static BOOL fixup_flags( WINDOWPOS *winpos )
|
|||
/* don't need to change the Zorder of hwnd if it's already inserted
|
||||
* after hwndInsertAfter or when inserting hwnd after itself.
|
||||
*/
|
||||
if ((wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
|
||||
if ((winpos->hwnd == winpos->hwndInsertAfter) ||
|
||||
(winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
|
||||
winpos->flags |= SWP_NOZORDER;
|
||||
}
|
||||
WIN_ReleaseWndPtr(wnd);
|
||||
|
@ -1306,20 +1307,6 @@ void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event )
|
|||
*
|
||||
* Synchronize internal z-order with the window manager's.
|
||||
*/
|
||||
static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
|
||||
{
|
||||
/* return TRUE if we have at least two managed windows */
|
||||
|
||||
for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
|
||||
if( ((*pWndA)->dwExStyle & WS_EX_MANAGED) &&
|
||||
((*pWndA)->dwStyle & WS_VISIBLE )) break;
|
||||
if( *pWndA )
|
||||
for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
|
||||
if( ((*pWndB)->dwExStyle & WS_EX_MANAGED) &&
|
||||
((*pWndB)->dwStyle & WS_VISIBLE )) break;
|
||||
return ((*pWndB) != NULL);
|
||||
}
|
||||
|
||||
static Window __get_common_ancestor( Display *display, Window A, Window B,
|
||||
Window** children, unsigned* total )
|
||||
{
|
||||
|
@ -1369,29 +1356,39 @@ static unsigned __td_lookup( Window w, Window* list, unsigned max )
|
|||
static HWND query_zorder( Display *display, HWND hWndCheck)
|
||||
{
|
||||
HWND hwndInsertAfter = HWND_TOP;
|
||||
WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
|
||||
WND *top = WIN_FindWndPtr( GetTopWindow(0) );
|
||||
WND *pWnd, *pWndZ = top;
|
||||
Window w, parent, *children = NULL;
|
||||
unsigned total, check, pos, best;
|
||||
HWND *list = WIN_ListChildren( GetDesktopWindow() );
|
||||
HWND hwndA = 0, hwndB = 0;
|
||||
WND *win;
|
||||
int i;
|
||||
|
||||
if( !__check_query_condition(&pWndZ, &pWnd) )
|
||||
/* find at least two managed windows */
|
||||
if (!list) return 0;
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
WIN_ReleaseWndPtr(pWndCheck);
|
||||
WIN_ReleaseWndPtr(top);
|
||||
return hwndInsertAfter;
|
||||
if (!(win = WIN_FindWndPtr( list[i] ))) continue;
|
||||
if ((win->dwExStyle & WS_EX_MANAGED) && (win->dwStyle & WS_VISIBLE))
|
||||
{
|
||||
if (!hwndA) hwndA = list[i];
|
||||
else
|
||||
{
|
||||
hwndB = list[i];
|
||||
WIN_ReleaseWndPtr( win );
|
||||
break;
|
||||
}
|
||||
}
|
||||
WIN_ReleaseWndPtr( win );
|
||||
}
|
||||
WIN_LockWndPtr(pWndZ);
|
||||
WIN_LockWndPtr(pWnd);
|
||||
WIN_ReleaseWndPtr(top);
|
||||
if (!hwndA || !hwndB) goto done;
|
||||
|
||||
parent = __get_common_ancestor( display, get_whole_window(pWndZ),
|
||||
get_whole_window(pWnd), &children, &total );
|
||||
parent = __get_common_ancestor( display, X11DRV_get_whole_window(hwndA),
|
||||
X11DRV_get_whole_window(hwndB), &children, &total );
|
||||
if( parent && children )
|
||||
{
|
||||
/* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
|
||||
/* w is the ancestor if hWndCheck that is a direct descendant of 'parent' */
|
||||
|
||||
w = __get_top_decoration( display, get_whole_window(pWndCheck), parent );
|
||||
w = __get_top_decoration( display, X11DRV_get_whole_window(hWndCheck), parent );
|
||||
|
||||
if( w != children[total-1] ) /* check if at the top */
|
||||
{
|
||||
|
@ -1399,32 +1396,28 @@ static HWND query_zorder( Display *display, HWND hWndCheck)
|
|||
check = __td_lookup( w, children, total );
|
||||
best = total;
|
||||
|
||||
for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
|
||||
/* go through all windows in Wine z-order... */
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
/* go through all windows in Wine z-order... */
|
||||
|
||||
if( pWnd != pWndCheck )
|
||||
if (list[i] == hWndCheck) continue;
|
||||
if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_MANAGED)) continue;
|
||||
if (!(w = __get_top_decoration( display, X11DRV_get_whole_window(list[i]),
|
||||
parent ))) continue;
|
||||
pos = __td_lookup( w, children, total );
|
||||
if( pos < best && pos > check )
|
||||
{
|
||||
if( !(pWnd->dwExStyle & WS_EX_MANAGED) ||
|
||||
!(w = __get_top_decoration( display, get_whole_window(pWnd), parent )) )
|
||||
continue;
|
||||
pos = __td_lookup( w, children, total );
|
||||
if( pos < best && pos > check )
|
||||
{
|
||||
/* find a nearest Wine window precedes
|
||||
* pWndCheck in the real z-order... */
|
||||
best = pos;
|
||||
hwndInsertAfter = pWnd->hwndSelf;
|
||||
}
|
||||
if( best - check == 1 ) break;
|
||||
/* find a nearest Wine window precedes hWndCheck in the real z-order */
|
||||
best = pos;
|
||||
hwndInsertAfter = list[i];
|
||||
}
|
||||
if( best - check == 1 ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( children ) TSXFree( children );
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
WIN_ReleaseWndPtr(pWndZ);
|
||||
WIN_ReleaseWndPtr(pWndCheck);
|
||||
|
||||
done:
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
return hwndInsertAfter;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,13 @@ struct tagMESSAGEQUEUE;
|
|||
|
||||
typedef struct tagWND
|
||||
{
|
||||
struct tagWND *next; /* Next sibling */
|
||||
struct tagWND *child; /* First child */
|
||||
HWND hwndSelf; /* Handle of this window */
|
||||
HWND parent; /* Window parent */
|
||||
HWND owner; /* Window owner */
|
||||
struct tagCLASS *class; /* Window class */
|
||||
HWINDOWPROC winproc; /* Window procedure */
|
||||
DWORD dwMagic; /* Magic number (must be WND_MAGIC) */
|
||||
DWORD tid; /* Owner thread id */
|
||||
HWND hwndSelf; /* Handle of this window */
|
||||
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
|
||||
RECT rectClient; /* Client area rel. to parent client area */
|
||||
RECT rectWindow; /* Whole window rel. to parent client area */
|
||||
|
@ -124,7 +122,7 @@ extern void CARET_GetRect(LPRECT lprc); /* windows/caret.c */
|
|||
extern BOOL16 DRAG_QueryUpdate( HWND, SEGPTR, BOOL );
|
||||
extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ); /* windows/defwnd.c */
|
||||
|
||||
extern void PROPERTY_RemoveWindowProps( WND *pWnd ); /* windows/property.c */
|
||||
extern void PROPERTY_RemoveWindowProps( HWND hwnd ); /* windows/property.c */
|
||||
|
||||
/* Classes functions */
|
||||
struct tagCLASS; /* opaque structure */
|
||||
|
|
|
@ -231,10 +231,12 @@ HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
|
|||
*
|
||||
* Remove all properties of a window.
|
||||
*/
|
||||
void PROPERTY_RemoveWindowProps( WND *pWnd )
|
||||
void PROPERTY_RemoveWindowProps( HWND hwnd )
|
||||
{
|
||||
PROPERTY *prop, *next;
|
||||
WND *pWnd = WIN_FindWndPtr( hwnd );
|
||||
|
||||
if (!pWnd) return;
|
||||
for (prop = pWnd->pProp; (prop); prop = next)
|
||||
{
|
||||
next = prop->next;
|
||||
|
@ -242,6 +244,7 @@ void PROPERTY_RemoveWindowProps( WND *pWnd )
|
|||
HeapFree( GetProcessHeap(), 0, prop );
|
||||
}
|
||||
pWnd->pProp = NULL;
|
||||
WIN_ReleaseWndPtr( pWnd );
|
||||
}
|
||||
|
||||
|
||||
|
|
212
windows/win.c
212
windows/win.c
|
@ -383,16 +383,8 @@ void WIN_UnlinkWindow( HWND hwnd )
|
|||
*/
|
||||
void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||
{
|
||||
WND *wndPtr, **ppWnd, *parentPtr = NULL;
|
||||
BOOL ret;
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
|
||||
if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
|
||||
{
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( link_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
|
@ -401,42 +393,88 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
|||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) goto done;
|
||||
|
||||
/* first unlink it if it is linked */
|
||||
if (wndPtr->parent)
|
||||
if (ret && parent)
|
||||
{
|
||||
WND *ptr = WIN_FindWndPtr( wndPtr->parent );
|
||||
ppWnd = &ptr->child;
|
||||
while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
|
||||
if (*ppWnd) *ppWnd = wndPtr->next;
|
||||
WIN_ReleaseWndPtr( ptr );
|
||||
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (wndPtr)
|
||||
{
|
||||
wndPtr->parent = WIN_GetFullHandle(parent);
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentPtr)
|
||||
|
||||
/***********************************************************************
|
||||
* find_child_to_repaint
|
||||
*
|
||||
* Find a window that needs repaint among the children of the specified window.
|
||||
*/
|
||||
static HWND find_child_to_repaint( HWND parent )
|
||||
{
|
||||
int i;
|
||||
HWND ret = 0;
|
||||
HWND *list;
|
||||
|
||||
if (!parent) parent = GetDesktopWindow();
|
||||
if (!(list = list_window_children( parent, 0, 0 ))) return 0;
|
||||
|
||||
for (i = 0; list[i] && !ret; i++)
|
||||
{
|
||||
wndPtr->parent = parentPtr->hwndSelf;
|
||||
if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
|
||||
WND *win = WIN_GetWndPtr( list[i] );
|
||||
if (win == BAD_WND_PTR) continue; /* ignore it */
|
||||
if (!win)
|
||||
{
|
||||
ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
|
||||
if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
|
||||
while (*ppWnd) ppWnd = &(*ppWnd)->next;
|
||||
/* doesn't belong to this process, but check children */
|
||||
ret = find_child_to_repaint( list[i] );
|
||||
continue;
|
||||
}
|
||||
else /* Normal case */
|
||||
if (!(win->dwStyle & WS_VISIBLE))
|
||||
{
|
||||
WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
|
||||
if (!afterPtr) goto done;
|
||||
ppWnd = &afterPtr->next;
|
||||
WIN_ReleaseWndPtr(afterPtr);
|
||||
USER_Unlock();
|
||||
continue;
|
||||
}
|
||||
if ((win->tid != GetCurrentThreadId()) ||
|
||||
(!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
|
||||
{
|
||||
/* does not need repaint, check children */
|
||||
USER_Unlock();
|
||||
ret = find_child_to_repaint( list[i] );
|
||||
continue;
|
||||
}
|
||||
wndPtr->next = *ppWnd;
|
||||
*ppWnd = wndPtr;
|
||||
}
|
||||
else wndPtr->next = NULL; /* unlinked */
|
||||
|
||||
done:
|
||||
WIN_ReleaseWndPtr( parentPtr );
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
/* now we have something */
|
||||
ret = list[i];
|
||||
if (!(win->dwExStyle & WS_EX_TRANSPARENT))
|
||||
{
|
||||
/* not transparent, we can repaint it */
|
||||
USER_Unlock();
|
||||
break;
|
||||
}
|
||||
USER_Unlock();
|
||||
|
||||
/* transparent window, look for non-transparent sibling to paint first */
|
||||
for (i++; list[i]; i++)
|
||||
{
|
||||
if (!(win = WIN_GetWndPtr( list[i] ))) continue;
|
||||
if (win == BAD_WND_PTR) continue;
|
||||
if (!(win->dwStyle & WS_VISIBLE))
|
||||
{
|
||||
USER_Unlock();
|
||||
continue;
|
||||
}
|
||||
if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
|
||||
(win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
|
||||
{
|
||||
ret = list[i];
|
||||
USER_Unlock();
|
||||
break;
|
||||
}
|
||||
USER_Unlock();
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -447,55 +485,27 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
|||
*/
|
||||
HWND WIN_FindWinToRepaint( HWND hwnd )
|
||||
{
|
||||
HWND hwndRet;
|
||||
WND *pWnd;
|
||||
|
||||
/* Note: the desktop window never gets WM_PAINT messages
|
||||
* The real reason why is because Windows DesktopWndProc
|
||||
* does ValidateRgn inside WM_ERASEBKGND handler.
|
||||
*/
|
||||
if (hwnd == GetDesktopWindow()) hwnd = 0;
|
||||
|
||||
pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
|
||||
|
||||
for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
|
||||
if (hwnd)
|
||||
{
|
||||
if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
|
||||
if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
|
||||
WIN_IsCurrentThread( pWnd->hwndSelf ))
|
||||
break;
|
||||
if (pWnd->child )
|
||||
/* check the window itself first */
|
||||
WND *win = WIN_FindWndPtr( hwnd );
|
||||
if (!win) return 0;
|
||||
if ((win->dwStyle & WS_VISIBLE) &&
|
||||
(win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
|
||||
{
|
||||
if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
|
||||
{
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
return hwndRet;
|
||||
}
|
||||
WIN_ReleaseWndPtr( win );
|
||||
return hwnd;
|
||||
}
|
||||
WIN_ReleaseWndPtr( win );
|
||||
}
|
||||
|
||||
if(!pWnd)
|
||||
{
|
||||
TRACE("nothing found\n");
|
||||
return 0;
|
||||
}
|
||||
hwndRet = pWnd->hwndSelf;
|
||||
|
||||
/* look among siblings if we got a transparent window */
|
||||
while (pWnd)
|
||||
{
|
||||
if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
|
||||
(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
|
||||
WIN_IsCurrentThread( pWnd->hwndSelf ))
|
||||
{
|
||||
hwndRet = pWnd->hwndSelf;
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
break;
|
||||
}
|
||||
WIN_UpdateWndPtr(&pWnd,pWnd->next);
|
||||
}
|
||||
TRACE("found %04x\n",hwndRet);
|
||||
return hwndRet;
|
||||
/* now check its children */
|
||||
return find_child_to_repaint( hwnd );
|
||||
}
|
||||
|
||||
|
||||
|
@ -503,34 +513,33 @@ HWND WIN_FindWinToRepaint( HWND hwnd )
|
|||
* WIN_DestroyWindow
|
||||
*
|
||||
* Destroy storage associated to a window. "Internals" p.358
|
||||
* returns a locked wndPtr->next
|
||||
*/
|
||||
static WND* WIN_DestroyWindow( WND* wndPtr )
|
||||
static void WIN_DestroyWindow( HWND hwnd )
|
||||
{
|
||||
HWND hwnd = wndPtr->hwndSelf;
|
||||
WND *pWnd;
|
||||
WND *wndPtr;
|
||||
HWND *list;
|
||||
|
||||
TRACE("%04x\n", wndPtr->hwndSelf );
|
||||
TRACE("%04x\n", hwnd );
|
||||
|
||||
/* free child windows */
|
||||
WIN_LockWndPtr(wndPtr->child);
|
||||
while ((pWnd = wndPtr->child))
|
||||
if ((list = WIN_ListChildren( hwnd )))
|
||||
{
|
||||
wndPtr->child = WIN_DestroyWindow( pWnd );
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
int i;
|
||||
for (i = 0; list[i]; i++) WIN_DestroyWindow( list[i] );
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the update region to make sure no WM_PAINT messages will be
|
||||
* generated for this window while processing the WM_NCDESTROY.
|
||||
*/
|
||||
RedrawWindow( wndPtr->hwndSelf, NULL, 0,
|
||||
RedrawWindow( hwnd, NULL, 0,
|
||||
RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
|
||||
|
||||
/*
|
||||
* Send the WM_NCDESTROY to the window being destroyed.
|
||||
*/
|
||||
SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
|
||||
SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
|
||||
|
||||
/* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
|
||||
|
||||
|
@ -539,12 +548,10 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
|
|||
|
||||
/* free resources associated with the window */
|
||||
|
||||
TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
|
||||
PROPERTY_RemoveWindowProps( wndPtr );
|
||||
TIMER_RemoveWindowTimers( hwnd );
|
||||
PROPERTY_RemoveWindowProps( hwnd );
|
||||
|
||||
/* toss stale messages from the queue */
|
||||
|
||||
QUEUE_CleanupWindow( hwnd );
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
|
||||
wndPtr->hmemTaskQ = 0;
|
||||
|
||||
if (!(wndPtr->dwStyle & WS_CHILD))
|
||||
|
@ -558,16 +565,13 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
|
|||
DestroyMenu( wndPtr->hSysMenu );
|
||||
wndPtr->hSysMenu = 0;
|
||||
}
|
||||
USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
|
||||
DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
|
||||
USER_Driver.pDestroyWindow( hwnd );
|
||||
DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
|
||||
WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
|
||||
CLASS_RemoveWindow( wndPtr->class );
|
||||
wndPtr->class = NULL;
|
||||
wndPtr->dwMagic = 0; /* Mark it as invalid */
|
||||
|
||||
WIN_UpdateWndPtr(&pWnd,wndPtr->next);
|
||||
|
||||
return pWnd;
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -622,8 +626,6 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
hwndDesktop = pWndDesktop->hwndSelf;
|
||||
|
||||
pWndDesktop->tid = 0; /* nobody owns the desktop */
|
||||
pWndDesktop->next = NULL;
|
||||
pWndDesktop->child = NULL;
|
||||
pWndDesktop->parent = 0;
|
||||
pWndDesktop->owner = 0;
|
||||
pWndDesktop->class = class;
|
||||
|
@ -838,10 +840,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
/* Fill the window structure */
|
||||
|
||||
wndPtr->tid = GetCurrentThreadId();
|
||||
wndPtr->next = NULL;
|
||||
wndPtr->child = NULL;
|
||||
wndPtr->owner = owner;
|
||||
wndPtr->tid = GetCurrentThreadId();
|
||||
wndPtr->owner = owner;
|
||||
wndPtr->parent = parent;
|
||||
wndPtr->class = classPtr;
|
||||
wndPtr->winproc = winproc;
|
||||
|
@ -960,12 +960,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
}
|
||||
else wndPtr->wIDmenu = (UINT)cs->hMenu;
|
||||
|
||||
if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
|
||||
if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
|
||||
{
|
||||
WARN("aborted by WM_xxCREATE!\n");
|
||||
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
WIN_DestroyWindow( hwnd );
|
||||
CLASS_RemoveWindow( classPtr );
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1352,7 +1352,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
|
|||
|
||||
/* Destroy the window storage */
|
||||
|
||||
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
|
||||
WIN_DestroyWindow( hwnd );
|
||||
retvalue = TRUE;
|
||||
end:
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
|
|
210
windows/winpos.c
210
windows/winpos.c
|
@ -282,6 +282,90 @@ BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* find_child_from_point
|
||||
*
|
||||
* Find the child that contains pt. Helper for WindowFromPoint.
|
||||
* pt is in parent client coordinates.
|
||||
* lparam is the param to pass in the WM_NCHITTEST message.
|
||||
*/
|
||||
static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
|
||||
{
|
||||
int i, res;
|
||||
WND *wndPtr;
|
||||
HWND *list = WIN_ListChildren( parent );
|
||||
|
||||
if (!list) return 0;
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
|
||||
/* If point is in window, and window is visible, and it */
|
||||
/* is enabled (or it's a top-level window), then explore */
|
||||
/* its children. Otherwise, go to the next window. */
|
||||
|
||||
if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next; /* not visible -> skip */
|
||||
if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
|
||||
goto next; /* disabled child -> skip */
|
||||
if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
|
||||
goto next; /* transparent -> skip */
|
||||
if (wndPtr->hrgnWnd)
|
||||
{
|
||||
if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left,
|
||||
pt.y - wndPtr->rectWindow.top ))
|
||||
goto next; /* point outside window region -> skip */
|
||||
}
|
||||
else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */
|
||||
|
||||
TRACE( "%ld,%ld is inside %04x\n", pt.x, pt.y, list[i] );
|
||||
|
||||
/* If window is minimized or disabled, return at once */
|
||||
if (wndPtr->dwStyle & WS_MINIMIZE)
|
||||
{
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
*hittest = HTCAPTION;
|
||||
return list[i];
|
||||
}
|
||||
if (wndPtr->dwStyle & WS_DISABLED)
|
||||
{
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
*hittest = HTERROR;
|
||||
return list[i];
|
||||
}
|
||||
|
||||
/* If point is in client area, explore children */
|
||||
if (PtInRect( &wndPtr->rectClient, pt ))
|
||||
{
|
||||
POINT new_pt;
|
||||
HWND ret;
|
||||
|
||||
new_pt.x = pt.x - wndPtr->rectClient.left;
|
||||
new_pt.y = pt.y - wndPtr->rectClient.top;
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
|
||||
return ret;
|
||||
}
|
||||
else WIN_ReleaseWndPtr( wndPtr );
|
||||
|
||||
/* Now it's inside window, send WM_NCCHITTEST (if same thread) */
|
||||
if (!WIN_IsCurrentThread( list[i] ))
|
||||
{
|
||||
*hittest = HTCLIENT;
|
||||
return list[i];
|
||||
}
|
||||
if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
|
||||
{
|
||||
*hittest = res; /* Found the window */
|
||||
return list[i];
|
||||
}
|
||||
continue; /* continue search with next sibling */
|
||||
|
||||
next:
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WINPOS_WindowFromPoint
|
||||
*
|
||||
|
@ -289,9 +373,9 @@ BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
|
|||
*/
|
||||
HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
|
||||
{
|
||||
WND *wndScope, *wndPtr, *wndTmp;
|
||||
HWND hwnd_ret = 0;
|
||||
WND *wndScope;
|
||||
POINT xy = pt;
|
||||
int res;
|
||||
|
||||
TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
|
||||
|
||||
|
@ -300,115 +384,41 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
|
|||
hwndScope = wndScope->hwndSelf; /* make it a full handle */
|
||||
|
||||
*hittest = HTERROR;
|
||||
wndPtr = WIN_LockWndPtr(wndScope->child);
|
||||
|
||||
if( wndScope->dwStyle & WS_DISABLED )
|
||||
{
|
||||
*hittest = HTERROR;
|
||||
goto end;
|
||||
WIN_ReleaseWndPtr(wndScope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wndScope->parent)
|
||||
MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
|
||||
|
||||
if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
|
||||
xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom ||
|
||||
wndScope->dwStyle & WS_MINIMIZE)
|
||||
goto hittest;
|
||||
|
||||
xy.x -= wndScope->rectClient.left;
|
||||
xy.y -= wndScope->rectClient.top;
|
||||
|
||||
for (;;)
|
||||
if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
|
||||
{
|
||||
while (wndPtr)
|
||||
{
|
||||
/* If point is in window, and window is visible, and it */
|
||||
/* is enabled (or it's a top-level window), then explore */
|
||||
/* its children. Otherwise, go to the next window. */
|
||||
HWND ret;
|
||||
|
||||
if ((wndPtr->dwStyle & WS_VISIBLE) &&
|
||||
((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
|
||||
(!(wndPtr->dwStyle & WS_DISABLED) ||
|
||||
((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
|
||||
(wndPtr->hrgnWnd ?
|
||||
PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
|
||||
xy.y - wndPtr->rectWindow.top) :
|
||||
((xy.x >= wndPtr->rectWindow.left) &&
|
||||
(xy.x < wndPtr->rectWindow.right) &&
|
||||
(xy.y >= wndPtr->rectWindow.top) &&
|
||||
(xy.y < wndPtr->rectWindow.bottom))))
|
||||
{
|
||||
TRACE("%ld,%ld is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
|
||||
hwnd_ret = wndPtr->hwndSelf; /* Got a suitable window */
|
||||
|
||||
/* If window is minimized or disabled, return at once */
|
||||
if (wndPtr->dwStyle & WS_MINIMIZE)
|
||||
{
|
||||
*hittest = HTCAPTION;
|
||||
goto end;
|
||||
}
|
||||
if (wndPtr->dwStyle & WS_DISABLED)
|
||||
{
|
||||
*hittest = HTERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* If point is not in client area, ignore the children */
|
||||
if ((xy.x < wndPtr->rectClient.left) ||
|
||||
(xy.x >= wndPtr->rectClient.right) ||
|
||||
(xy.y < wndPtr->rectClient.top) ||
|
||||
(xy.y >= wndPtr->rectClient.bottom)) break;
|
||||
|
||||
xy.x -= wndPtr->rectClient.left;
|
||||
xy.y -= wndPtr->rectClient.top;
|
||||
WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
|
||||
}
|
||||
}
|
||||
|
||||
hittest:
|
||||
/* If nothing found, try the scope window */
|
||||
if (!hwnd_ret) hwnd_ret = hwndScope;
|
||||
|
||||
/* Send the WM_NCHITTEST message (only if to the same task) */
|
||||
if (WIN_IsCurrentThread( hwnd_ret ))
|
||||
{
|
||||
INT res = SendMessageA( hwnd_ret, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
|
||||
if (res != HTTRANSPARENT)
|
||||
{
|
||||
*hittest = res; /* Found the window */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*hittest = HTCLIENT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(wndTmp = WIN_FindWndPtr( hwnd_ret ))) break;
|
||||
|
||||
/* If no children found in last search, make point relative to parent */
|
||||
if (!wndPtr)
|
||||
{
|
||||
xy.x += wndTmp->rectClient.left;
|
||||
xy.y += wndTmp->rectClient.top;
|
||||
}
|
||||
|
||||
/* Restart the search from the next sibling */
|
||||
WIN_UpdateWndPtr(&wndPtr,wndTmp->next);
|
||||
hwnd_ret = wndTmp->parent;
|
||||
WIN_ReleaseWndPtr( wndTmp );
|
||||
xy.x -= wndScope->rectClient.left;
|
||||
xy.y -= wndScope->rectClient.top;
|
||||
WIN_ReleaseWndPtr( wndScope );
|
||||
if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
|
||||
return ret;
|
||||
}
|
||||
else WIN_ReleaseWndPtr( wndScope );
|
||||
|
||||
end:
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
WIN_ReleaseWndPtr(wndScope);
|
||||
return hwnd_ret;
|
||||
/* If nothing found, try the scope window */
|
||||
if (!WIN_IsCurrentThread( hwndScope ))
|
||||
{
|
||||
*hittest = HTCLIENT;
|
||||
return hwndScope;
|
||||
}
|
||||
res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
|
||||
if (res != HTTRANSPARENT)
|
||||
{
|
||||
*hittest = res; /* Found the window */
|
||||
return hwndScope;
|
||||
}
|
||||
*hittest = HTNOWHERE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue