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
|
* adding to the clip region the intersection of the target rectangle
|
||||||
* with an offset window 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;
|
RECT rect;
|
||||||
WND *pWnd;
|
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;
|
if (list[i] == end) break;
|
||||||
|
if (!(pWnd = WIN_FindWndPtr( list[i] ))) continue;
|
||||||
rect.left = pWnd->rectWindow.left + x;
|
if (pWnd->dwStyle & WS_VISIBLE)
|
||||||
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 )) 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;
|
HeapFree( GetProcessHeap(), 0, list );
|
||||||
WIN_ReleaseWndPtr(pWnd);
|
|
||||||
return (start == end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,7 +238,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
||||||
* DCE_GetVisRect() returns a rectangle either in client
|
* DCE_GetVisRect() returns a rectangle either in client
|
||||||
* or in window coordinates (for DCX_WINDOW request). */
|
* or in window coordinates (for DCX_WINDOW request). */
|
||||||
|
|
||||||
if( (flags & DCX_CLIPCHILDREN) && wndPtr->child )
|
if (flags & DCX_CLIPCHILDREN)
|
||||||
{
|
{
|
||||||
if( flags & DCX_WINDOW )
|
if( flags & DCX_WINDOW )
|
||||||
{
|
{
|
||||||
|
@ -243,7 +251,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
||||||
else
|
else
|
||||||
xoffset = yoffset = 0;
|
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
|
/* 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
|
* preference dialogs) gets here, we take the region for the parent window
|
||||||
* but apparently still need to clip the children of the child 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 )
|
if( flags & DCX_WINDOW )
|
||||||
{
|
{
|
||||||
|
@ -268,7 +276,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
||||||
xoffset += childWnd->rectClient.left;
|
xoffset += childWnd->rectClient.left;
|
||||||
yoffset += childWnd->rectClient.top;
|
yoffset += childWnd->rectClient.top;
|
||||||
|
|
||||||
DCE_AddClipRects( childWnd->child->hwndSelf, 0, hrgnClip,
|
DCE_AddClipRects( childWnd->hwndSelf, 0, hrgnClip,
|
||||||
&rect, xoffset, yoffset );
|
&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 )
|
if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
|
||||||
DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
|
DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
|
||||||
wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
|
hrgnClip, &rect, xoffset, yoffset );
|
||||||
|
|
||||||
/* Clip siblings of all ancestors that have the
|
/* Clip siblings of all ancestors that have the
|
||||||
* WS_CLIPSIBLINGS style
|
* WS_CLIPSIBLINGS style
|
||||||
|
@ -303,8 +311,8 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
|
||||||
yoffset -= wndPtr->rectClient.top;
|
yoffset -= wndPtr->rectClient.top;
|
||||||
if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
|
if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
|
||||||
{
|
{
|
||||||
DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
|
DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
|
||||||
wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
|
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
|
/* don't need to change the Zorder of hwnd if it's already inserted
|
||||||
* after hwndInsertAfter or when inserting hwnd after itself.
|
* 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;
|
winpos->flags |= SWP_NOZORDER;
|
||||||
}
|
}
|
||||||
WIN_ReleaseWndPtr(wnd);
|
WIN_ReleaseWndPtr(wnd);
|
||||||
|
@ -543,7 +552,10 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( winpos->hwndInsertAfter == HWND_BOTTOM )
|
if( winpos->hwndInsertAfter == HWND_BOTTOM )
|
||||||
winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
|
{
|
||||||
|
if (!GetWindow( wndPtr->hwndSelf, GW_HWNDNEXT ))
|
||||||
|
winpos->flags |= SWP_NOZORDER;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if( !(winpos->flags & SWP_NOZORDER) )
|
if( !(winpos->flags & SWP_NOZORDER) )
|
||||||
if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
|
if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
|
||||||
|
|
|
@ -144,12 +144,14 @@ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
|
||||||
RECT rc, cliprc;
|
RECT rc, cliprc;
|
||||||
WND* wnd = WIN_FindWndPtr( hwnd );
|
WND* wnd = WIN_FindWndPtr( hwnd );
|
||||||
|
|
||||||
if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE ))
|
if (!wnd) return ERROR;
|
||||||
|
if (!WIN_IsWindowDrawable( wnd, TRUE ))
|
||||||
{
|
{
|
||||||
retVal = ERROR;
|
WIN_ReleaseWndPtr( wnd );
|
||||||
goto END;
|
return ERROR;
|
||||||
}
|
}
|
||||||
hwnd = wnd->hwndSelf; /* make it a full handle */
|
hwnd = wnd->hwndSelf; /* make it a full handle */
|
||||||
|
WIN_ReleaseWndPtr( wnd );
|
||||||
|
|
||||||
GetClientRect(hwnd, &rc);
|
GetClientRect(hwnd, &rc);
|
||||||
if (rect) IntersectRect(&rc, &rc, rect);
|
if (rect) IntersectRect(&rc, &rc, rect);
|
||||||
|
@ -203,16 +205,22 @@ INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
|
||||||
|
|
||||||
if( flags & SW_SCROLLCHILDREN )
|
if( flags & SW_SCROLLCHILDREN )
|
||||||
{
|
{
|
||||||
RECT r;
|
HWND *list = WIN_ListChildren( hwnd );
|
||||||
WND *w;
|
|
||||||
for( w =WIN_LockWndPtr(wnd->child); w; WIN_UpdateWndPtr(&w, w->next))
|
if (list)
|
||||||
{
|
{
|
||||||
r = w->rectWindow;
|
int i;
|
||||||
if( !rect || IntersectRect(&r, &r, &rc) )
|
RECT r, dummy;
|
||||||
SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
|
for (i = 0; list[i]; i++)
|
||||||
w->rectWindow.top + dy, 0,0, SWP_NOZORDER |
|
{
|
||||||
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
|
GetWindowRect( list[i], &r );
|
||||||
SWP_DEFERERASE );
|
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 );
|
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
|
||||||
DeleteObject( hrgnClip );
|
DeleteObject( hrgnClip );
|
||||||
}
|
}
|
||||||
END:
|
|
||||||
WIN_ReleaseWndPtr(wnd);
|
|
||||||
return retVal;
|
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
|
/* don't need to change the Zorder of hwnd if it's already inserted
|
||||||
* after hwndInsertAfter or when inserting hwnd after itself.
|
* 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;
|
winpos->flags |= SWP_NOZORDER;
|
||||||
}
|
}
|
||||||
WIN_ReleaseWndPtr(wnd);
|
WIN_ReleaseWndPtr(wnd);
|
||||||
|
@ -1306,20 +1307,6 @@ void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event )
|
||||||
*
|
*
|
||||||
* Synchronize internal z-order with the window manager's.
|
* 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,
|
static Window __get_common_ancestor( Display *display, Window A, Window B,
|
||||||
Window** children, unsigned* total )
|
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)
|
static HWND query_zorder( Display *display, HWND hWndCheck)
|
||||||
{
|
{
|
||||||
HWND hwndInsertAfter = HWND_TOP;
|
HWND hwndInsertAfter = HWND_TOP;
|
||||||
WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
|
|
||||||
WND *top = WIN_FindWndPtr( GetTopWindow(0) );
|
|
||||||
WND *pWnd, *pWndZ = top;
|
|
||||||
Window w, parent, *children = NULL;
|
Window w, parent, *children = NULL;
|
||||||
unsigned total, check, pos, best;
|
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);
|
if (!(win = WIN_FindWndPtr( list[i] ))) continue;
|
||||||
WIN_ReleaseWndPtr(top);
|
if ((win->dwExStyle & WS_EX_MANAGED) && (win->dwStyle & WS_VISIBLE))
|
||||||
return hwndInsertAfter;
|
{
|
||||||
|
if (!hwndA) hwndA = list[i];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hwndB = list[i];
|
||||||
|
WIN_ReleaseWndPtr( win );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WIN_ReleaseWndPtr( win );
|
||||||
}
|
}
|
||||||
WIN_LockWndPtr(pWndZ);
|
if (!hwndA || !hwndB) goto done;
|
||||||
WIN_LockWndPtr(pWnd);
|
|
||||||
WIN_ReleaseWndPtr(top);
|
|
||||||
|
|
||||||
parent = __get_common_ancestor( display, get_whole_window(pWndZ),
|
parent = __get_common_ancestor( display, X11DRV_get_whole_window(hwndA),
|
||||||
get_whole_window(pWnd), &children, &total );
|
X11DRV_get_whole_window(hwndB), &children, &total );
|
||||||
if( parent && children )
|
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 */
|
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 );
|
check = __td_lookup( w, children, total );
|
||||||
best = 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 (list[i] == hWndCheck) continue;
|
||||||
|
if (!(GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_MANAGED)) continue;
|
||||||
if( pWnd != pWndCheck )
|
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) ||
|
/* find a nearest Wine window precedes hWndCheck in the real z-order */
|
||||||
!(w = __get_top_decoration( display, get_whole_window(pWnd), parent )) )
|
best = pos;
|
||||||
continue;
|
hwndInsertAfter = list[i];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
if( best - check == 1 ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( children ) TSXFree( children );
|
if( children ) TSXFree( children );
|
||||||
WIN_ReleaseWndPtr(pWnd);
|
|
||||||
WIN_ReleaseWndPtr(pWndZ);
|
done:
|
||||||
WIN_ReleaseWndPtr(pWndCheck);
|
HeapFree( GetProcessHeap(), 0, list );
|
||||||
return hwndInsertAfter;
|
return hwndInsertAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,13 @@ struct tagMESSAGEQUEUE;
|
||||||
|
|
||||||
typedef struct tagWND
|
typedef struct tagWND
|
||||||
{
|
{
|
||||||
struct tagWND *next; /* Next sibling */
|
HWND hwndSelf; /* Handle of this window */
|
||||||
struct tagWND *child; /* First child */
|
|
||||||
HWND parent; /* Window parent */
|
HWND parent; /* Window parent */
|
||||||
HWND owner; /* Window owner */
|
HWND owner; /* Window owner */
|
||||||
struct tagCLASS *class; /* Window class */
|
struct tagCLASS *class; /* Window class */
|
||||||
HWINDOWPROC winproc; /* Window procedure */
|
HWINDOWPROC winproc; /* Window procedure */
|
||||||
DWORD dwMagic; /* Magic number (must be WND_MAGIC) */
|
DWORD dwMagic; /* Magic number (must be WND_MAGIC) */
|
||||||
DWORD tid; /* Owner thread id */
|
DWORD tid; /* Owner thread id */
|
||||||
HWND hwndSelf; /* Handle of this window */
|
|
||||||
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
|
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
|
||||||
RECT rectClient; /* Client area rel. to parent client area */
|
RECT rectClient; /* Client area rel. to parent client area */
|
||||||
RECT rectWindow; /* Whole window 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 BOOL16 DRAG_QueryUpdate( HWND, SEGPTR, BOOL );
|
||||||
extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ); /* windows/defwnd.c */
|
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 */
|
/* Classes functions */
|
||||||
struct tagCLASS; /* opaque structure */
|
struct tagCLASS; /* opaque structure */
|
||||||
|
|
|
@ -231,10 +231,12 @@ HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
|
||||||
*
|
*
|
||||||
* Remove all properties of a window.
|
* Remove all properties of a window.
|
||||||
*/
|
*/
|
||||||
void PROPERTY_RemoveWindowProps( WND *pWnd )
|
void PROPERTY_RemoveWindowProps( HWND hwnd )
|
||||||
{
|
{
|
||||||
PROPERTY *prop, *next;
|
PROPERTY *prop, *next;
|
||||||
|
WND *pWnd = WIN_FindWndPtr( hwnd );
|
||||||
|
|
||||||
|
if (!pWnd) return;
|
||||||
for (prop = pWnd->pProp; (prop); prop = next)
|
for (prop = pWnd->pProp; (prop); prop = next)
|
||||||
{
|
{
|
||||||
next = prop->next;
|
next = prop->next;
|
||||||
|
@ -242,6 +244,7 @@ void PROPERTY_RemoveWindowProps( WND *pWnd )
|
||||||
HeapFree( GetProcessHeap(), 0, prop );
|
HeapFree( GetProcessHeap(), 0, prop );
|
||||||
}
|
}
|
||||||
pWnd->pProp = NULL;
|
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 )
|
void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||||
{
|
{
|
||||||
WND *wndPtr, **ppWnd, *parentPtr = NULL;
|
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
|
|
||||||
if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
|
|
||||||
{
|
|
||||||
WIN_ReleaseWndPtr(wndPtr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SERVER_START_REQ( link_window )
|
SERVER_START_REQ( link_window )
|
||||||
{
|
{
|
||||||
req->handle = hwnd;
|
req->handle = hwnd;
|
||||||
|
@ -401,42 +393,88 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||||
ret = !SERVER_CALL_ERR();
|
ret = !SERVER_CALL_ERR();
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
if (!ret) goto done;
|
if (ret && parent)
|
||||||
|
|
||||||
/* first unlink it if it is linked */
|
|
||||||
if (wndPtr->parent)
|
|
||||||
{
|
{
|
||||||
WND *ptr = WIN_FindWndPtr( wndPtr->parent );
|
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||||
ppWnd = &ptr->child;
|
if (wndPtr)
|
||||||
while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
|
{
|
||||||
if (*ppWnd) *ppWnd = wndPtr->next;
|
wndPtr->parent = WIN_GetFullHandle(parent);
|
||||||
WIN_ReleaseWndPtr( ptr );
|
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;
|
WND *win = WIN_GetWndPtr( list[i] );
|
||||||
if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
|
if (win == BAD_WND_PTR) continue; /* ignore it */
|
||||||
|
if (!win)
|
||||||
{
|
{
|
||||||
ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
|
/* doesn't belong to this process, but check children */
|
||||||
if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
|
ret = find_child_to_repaint( list[i] );
|
||||||
while (*ppWnd) ppWnd = &(*ppWnd)->next;
|
continue;
|
||||||
}
|
}
|
||||||
else /* Normal case */
|
if (!(win->dwStyle & WS_VISIBLE))
|
||||||
{
|
{
|
||||||
WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
|
USER_Unlock();
|
||||||
if (!afterPtr) goto done;
|
continue;
|
||||||
ppWnd = &afterPtr->next;
|
}
|
||||||
WIN_ReleaseWndPtr(afterPtr);
|
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:
|
/* now we have something */
|
||||||
WIN_ReleaseWndPtr( parentPtr );
|
ret = list[i];
|
||||||
WIN_ReleaseWndPtr( wndPtr );
|
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 WIN_FindWinToRepaint( HWND hwnd )
|
||||||
{
|
{
|
||||||
HWND hwndRet;
|
|
||||||
WND *pWnd;
|
|
||||||
|
|
||||||
/* Note: the desktop window never gets WM_PAINT messages
|
/* Note: the desktop window never gets WM_PAINT messages
|
||||||
* The real reason why is because Windows DesktopWndProc
|
* The real reason why is because Windows DesktopWndProc
|
||||||
* does ValidateRgn inside WM_ERASEBKGND handler.
|
* does ValidateRgn inside WM_ERASEBKGND handler.
|
||||||
*/
|
*/
|
||||||
if (hwnd == GetDesktopWindow()) hwnd = 0;
|
if (hwnd == GetDesktopWindow()) hwnd = 0;
|
||||||
|
|
||||||
pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
|
if (hwnd)
|
||||||
|
|
||||||
for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
|
|
||||||
{
|
{
|
||||||
if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
|
/* check the window itself first */
|
||||||
if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
|
WND *win = WIN_FindWndPtr( hwnd );
|
||||||
WIN_IsCurrentThread( pWnd->hwndSelf ))
|
if (!win) return 0;
|
||||||
break;
|
if ((win->dwStyle & WS_VISIBLE) &&
|
||||||
if (pWnd->child )
|
(win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
|
||||||
{
|
{
|
||||||
if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
|
WIN_ReleaseWndPtr( win );
|
||||||
{
|
return hwnd;
|
||||||
WIN_ReleaseWndPtr(pWnd);
|
|
||||||
return hwndRet;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
WIN_ReleaseWndPtr( win );
|
||||||
}
|
}
|
||||||
|
/* now check its children */
|
||||||
if(!pWnd)
|
return find_child_to_repaint( hwnd );
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -503,34 +513,33 @@ HWND WIN_FindWinToRepaint( HWND hwnd )
|
||||||
* WIN_DestroyWindow
|
* WIN_DestroyWindow
|
||||||
*
|
*
|
||||||
* Destroy storage associated to a window. "Internals" p.358
|
* 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 *wndPtr;
|
||||||
WND *pWnd;
|
HWND *list;
|
||||||
|
|
||||||
TRACE("%04x\n", wndPtr->hwndSelf );
|
TRACE("%04x\n", hwnd );
|
||||||
|
|
||||||
/* free child windows */
|
/* free child windows */
|
||||||
WIN_LockWndPtr(wndPtr->child);
|
if ((list = WIN_ListChildren( hwnd )))
|
||||||
while ((pWnd = wndPtr->child))
|
|
||||||
{
|
{
|
||||||
wndPtr->child = WIN_DestroyWindow( pWnd );
|
int i;
|
||||||
WIN_ReleaseWndPtr(pWnd);
|
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
|
* Clear the update region to make sure no WM_PAINT messages will be
|
||||||
* generated for this window while processing the WM_NCDESTROY.
|
* 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);
|
RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send the WM_NCDESTROY to the window being destroyed.
|
* 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? */
|
/* 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 */
|
/* free resources associated with the window */
|
||||||
|
|
||||||
TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
|
TIMER_RemoveWindowTimers( hwnd );
|
||||||
PROPERTY_RemoveWindowProps( wndPtr );
|
PROPERTY_RemoveWindowProps( hwnd );
|
||||||
|
|
||||||
/* toss stale messages from the queue */
|
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
|
||||||
|
|
||||||
QUEUE_CleanupWindow( hwnd );
|
|
||||||
wndPtr->hmemTaskQ = 0;
|
wndPtr->hmemTaskQ = 0;
|
||||||
|
|
||||||
if (!(wndPtr->dwStyle & WS_CHILD))
|
if (!(wndPtr->dwStyle & WS_CHILD))
|
||||||
|
@ -558,16 +565,13 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
|
||||||
DestroyMenu( wndPtr->hSysMenu );
|
DestroyMenu( wndPtr->hSysMenu );
|
||||||
wndPtr->hSysMenu = 0;
|
wndPtr->hSysMenu = 0;
|
||||||
}
|
}
|
||||||
USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
|
USER_Driver.pDestroyWindow( hwnd );
|
||||||
DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
|
DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
|
||||||
WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
|
WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
|
||||||
CLASS_RemoveWindow( wndPtr->class );
|
CLASS_RemoveWindow( wndPtr->class );
|
||||||
wndPtr->class = NULL;
|
wndPtr->class = NULL;
|
||||||
wndPtr->dwMagic = 0; /* Mark it as invalid */
|
wndPtr->dwMagic = 0; /* Mark it as invalid */
|
||||||
|
WIN_ReleaseWndPtr( wndPtr );
|
||||||
WIN_UpdateWndPtr(&pWnd,wndPtr->next);
|
|
||||||
|
|
||||||
return pWnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -622,8 +626,6 @@ BOOL WIN_CreateDesktopWindow(void)
|
||||||
hwndDesktop = pWndDesktop->hwndSelf;
|
hwndDesktop = pWndDesktop->hwndSelf;
|
||||||
|
|
||||||
pWndDesktop->tid = 0; /* nobody owns the desktop */
|
pWndDesktop->tid = 0; /* nobody owns the desktop */
|
||||||
pWndDesktop->next = NULL;
|
|
||||||
pWndDesktop->child = NULL;
|
|
||||||
pWndDesktop->parent = 0;
|
pWndDesktop->parent = 0;
|
||||||
pWndDesktop->owner = 0;
|
pWndDesktop->owner = 0;
|
||||||
pWndDesktop->class = class;
|
pWndDesktop->class = class;
|
||||||
|
@ -838,10 +840,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
||||||
|
|
||||||
/* Fill the window structure */
|
/* Fill the window structure */
|
||||||
|
|
||||||
wndPtr->tid = GetCurrentThreadId();
|
wndPtr->tid = GetCurrentThreadId();
|
||||||
wndPtr->next = NULL;
|
wndPtr->owner = owner;
|
||||||
wndPtr->child = NULL;
|
|
||||||
wndPtr->owner = owner;
|
|
||||||
wndPtr->parent = parent;
|
wndPtr->parent = parent;
|
||||||
wndPtr->class = classPtr;
|
wndPtr->class = classPtr;
|
||||||
wndPtr->winproc = winproc;
|
wndPtr->winproc = winproc;
|
||||||
|
@ -960,12 +960,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
||||||
}
|
}
|
||||||
else wndPtr->wIDmenu = (UINT)cs->hMenu;
|
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");
|
WARN("aborted by WM_xxCREATE!\n");
|
||||||
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
|
WIN_ReleaseWndPtr( wndPtr );
|
||||||
|
WIN_DestroyWindow( hwnd );
|
||||||
CLASS_RemoveWindow( classPtr );
|
CLASS_RemoveWindow( classPtr );
|
||||||
WIN_ReleaseWndPtr(wndPtr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,7 +1352,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
|
||||||
|
|
||||||
/* Destroy the window storage */
|
/* Destroy the window storage */
|
||||||
|
|
||||||
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
|
WIN_DestroyWindow( hwnd );
|
||||||
retvalue = TRUE;
|
retvalue = TRUE;
|
||||||
end:
|
end:
|
||||||
WIN_ReleaseWndPtr(wndPtr);
|
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
|
* WINPOS_WindowFromPoint
|
||||||
*
|
*
|
||||||
|
@ -289,9 +373,9 @@ BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
|
||||||
*/
|
*/
|
||||||
HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
|
HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
|
||||||
{
|
{
|
||||||
WND *wndScope, *wndPtr, *wndTmp;
|
WND *wndScope;
|
||||||
HWND hwnd_ret = 0;
|
|
||||||
POINT xy = pt;
|
POINT xy = pt;
|
||||||
|
int res;
|
||||||
|
|
||||||
TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
|
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 */
|
hwndScope = wndScope->hwndSelf; /* make it a full handle */
|
||||||
|
|
||||||
*hittest = HTERROR;
|
*hittest = HTERROR;
|
||||||
wndPtr = WIN_LockWndPtr(wndScope->child);
|
|
||||||
|
|
||||||
if( wndScope->dwStyle & WS_DISABLED )
|
if( wndScope->dwStyle & WS_DISABLED )
|
||||||
{
|
{
|
||||||
*hittest = HTERROR;
|
WIN_ReleaseWndPtr(wndScope);
|
||||||
goto end;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndScope->parent)
|
if (wndScope->parent)
|
||||||
MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
|
MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
|
||||||
|
|
||||||
if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
|
if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
|
||||||
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 (;;)
|
|
||||||
{
|
{
|
||||||
while (wndPtr)
|
HWND ret;
|
||||||
{
|
|
||||||
/* 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) &&
|
xy.x -= wndScope->rectClient.left;
|
||||||
((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
|
xy.y -= wndScope->rectClient.top;
|
||||||
(!(wndPtr->dwStyle & WS_DISABLED) ||
|
WIN_ReleaseWndPtr( wndScope );
|
||||||
((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
|
if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
|
||||||
(wndPtr->hrgnWnd ?
|
return ret;
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
else WIN_ReleaseWndPtr( wndScope );
|
||||||
|
|
||||||
end:
|
/* If nothing found, try the scope window */
|
||||||
WIN_ReleaseWndPtr(wndPtr);
|
if (!WIN_IsCurrentThread( hwndScope ))
|
||||||
WIN_ReleaseWndPtr(wndScope);
|
{
|
||||||
return hwnd_ret;
|
*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