Newer
Older
* 1995, 1996, 1999 Alex Korobka
#include "winerror.h"
#include "windef.h"
#include "wingdi.h"
#include "wine/winuser16.h"
#include "controls.h"
#include "region.h"
#include "debugtools.h"
#include "input.h"
DEFAULT_DEBUG_CHANNEL(win);
#define HAS_DLGFRAME(style,exStyle) \
(((exStyle) & WS_EX_DLGMODALFRAME) || \
(((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
#define HAS_THICKFRAME(style) \
(((style) & WS_THICKFRAME) && \
!(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
#define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
#define PLACE_MIN 0x0001
#define PLACE_MAX 0x0002
#define PLACE_RECT 0x0004
#define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
typedef struct
{
INT actualCount;
INT suggestedCount;
BOOL valid;
INT wMagic;
HWND hwndParent;
WINDOWPOS winPos[1];
} DWP;
static HWND hwndPrevActive = 0; /* Previously active window */
static HWND hGlobalShellWindow=0; /*the shell*/
static HWND hGlobalTaskmanWindow=0;
static HWND hGlobalProgmanWindow=0;
extern HQUEUE16 hActiveQueue;
/***********************************************************************
BOOL WINPOS_CreateInternalPosAtom()
atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
return (atomInternalPos) ? TRUE : FALSE;
}
/***********************************************************************
* WINPOS_CheckInternalPos
*
* Called when a window is destroyed.
*/
void WINPOS_CheckInternalPos( HWND hwnd )
LPINTERNALPOS lpPos;
MESSAGEQUEUE *pMsgQ = 0;
WND *wndPtr = WIN_FindWndPtr( hwnd );
lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
/* Retrieve the message queue associated with this window */
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
if ( !pMsgQ )
{
WARN("\tMessage queue not found. Exiting!\n" );
WIN_ReleaseWndPtr( wndPtr );
return;
}
if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
WARN("\tattempt to activate destroyed window!\n");
if( IsWindow(lpPos->hwndIconTitle) )
DestroyWindow( lpPos->hwndIconTitle );
HeapFree( GetProcessHeap(), 0, lpPos );
QUEUE_Unlock( pMsgQ );
WIN_ReleaseWndPtr( wndPtr );
/***********************************************************************
UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
return ArrangeIconicWindows(parent);
/***********************************************************************
UINT WINAPI ArrangeIconicWindows( HWND parent )
RECT rectParent;
HWND hwndChild;
INT x, y, xspacing, yspacing;
GetClientRect( parent, &rectParent );
xspacing = GetSystemMetrics(SM_CXICONSPACING);
yspacing = GetSystemMetrics(SM_CYICONSPACING);
hwndChild = GetWindow( parent, GW_CHILD );
if( IsIconic( hwndChild ) )
WINPOS_ShowIconTitle( hwndChild, FALSE );
SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
if( IsWindow(hwndChild) )
WINPOS_ShowIconTitle(hwndChild , TRUE );
if (x <= rectParent.right - xspacing) x += xspacing;
else
{
x = rectParent.left;
y -= yspacing;
}
}
hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
/***********************************************************************
void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
SwitchToThisWindow( hwnd, restore );
}
/***********************************************************************
void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
/***********************************************************************
void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (wndPtr->parent)
MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
WIN_ReleaseWndPtr(wndPtr);
}
/***********************************************************************
BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
if (wndPtr->parent)
MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
WIN_ReleaseWndPtr(wndPtr);
TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
hwnd, rect->left, rect->top, rect->right, rect->bottom);
/***********************************************************************
int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{
int nRet = ERROR;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if (wndPtr)
{
if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
WIN_ReleaseWndPtr(wndPtr);
}
return nRet;
}
/***********************************************************************
*/
int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
RECT rect;
WND *wndPtr;
if (USER_Driver.pSetWindowRgn)
return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
if (wndPtr->hrgnWnd == hrgn)
ret = TRUE;
if (hrgn) /* verify that region really exists */
if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
if (wndPtr->hrgnWnd)
{
/* delete previous region */
DeleteObject(wndPtr->hrgnWnd);
wndPtr->hrgnWnd = 0;
}
wndPtr->hrgnWnd = hrgn;
/* Size the window to the rectangle of the new region (if it isn't NULL) */
if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
ret = TRUE;
done:
WIN_ReleaseWndPtr(wndPtr);
return ret;
/***********************************************************************
*/
INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
{
FIXME("SetWindowRgn16: stub\n");
/***********************************************************************
void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
rect->left = rect->top = rect->right = rect->bottom = 0;
if (wndPtr)
{
rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
}
WIN_ReleaseWndPtr(wndPtr);
}
/***********************************************************************
BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
rect->left = rect->top = rect->right = rect->bottom = 0;
if (!wndPtr) return FALSE;
rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
WIN_ReleaseWndPtr(wndPtr);
TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
hwnd, rect->left, rect->top, rect->right, rect->bottom);
}
/*******************************************************************
void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
}
/*******************************************************************
BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
MapWindowPoints( hwnd, 0, lppnt, 1 );
return TRUE;
}
/*******************************************************************
void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
{
MapWindowPoints16( 0, hwnd, lppnt, 1 );
}
/*******************************************************************
BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
MapWindowPoints( 0, hwnd, lppnt, 1 );
/***********************************************************************
* WINPOS_WindowFromPoint

Alexandre Julliard
committed
HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )

Alexandre Julliard
committed
WND *wndScope, *wndPtr, *wndTmp;
HWND hwnd_ret = 0;
POINT xy = pt;

Alexandre Julliard
committed
TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
if (!hwndScope) hwndScope = GetDesktopWindow();
if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
*hittest = HTERROR;
wndPtr = WIN_LockWndPtr(wndScope->child);
if( wndScope->dwStyle & WS_DISABLED )
{

Alexandre Julliard
committed
*hittest = HTERROR;
goto end;
}
if (wndScope->parent)
MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &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;
{
/* 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) &&
((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);

Alexandre Julliard
committed
hwnd_ret = wndPtr->hwndSelf; /* Got a suitable window */
/* If window is minimized or disabled, return at once */
if (wndPtr->dwStyle & WS_MINIMIZE)
{

Alexandre Julliard
committed
*hittest = HTCAPTION;
goto end;
}
if (wndPtr->dwStyle & WS_DISABLED)
{

Alexandre Julliard
committed
*hittest = HTERROR;
/* 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);

Alexandre Julliard
committed
if (!hwnd_ret) hwnd_ret = hwndScope;
/* Send the WM_NCHITTEST message (only if to the same task) */

Alexandre Julliard
committed
if (GetWindowThreadProcessId( hwnd_ret, NULL ) == GetCurrentThreadId())

Alexandre Julliard
committed
INT res = SendMessageA( hwnd_ret, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
if (res != HTTRANSPARENT)

Alexandre Julliard
committed
*hittest = res; /* Found the window */

Alexandre Julliard
committed
*hittest = HTCLIENT;

Alexandre Julliard
committed
if (!(wndTmp = WIN_FindWndPtr( hwnd_ret ))) break;
/* If no children found in last search, make point relative to parent */

Alexandre Julliard
committed
xy.x += wndTmp->rectClient.left;
xy.y += wndTmp->rectClient.top;
}
/* Restart the search from the next sibling */

Alexandre Julliard
committed
WIN_UpdateWndPtr(&wndPtr,wndTmp->next);
hwnd_ret = wndTmp->parent ? wndTmp->parent->hwndSelf : 0;
WIN_ReleaseWndPtr( wndTmp );
end:
WIN_ReleaseWndPtr(wndPtr);

Alexandre Julliard
committed
WIN_ReleaseWndPtr(wndScope);
return hwnd_ret;
/*******************************************************************
POINT pt32;
CONV_POINT16TO32( &pt, &pt32 );
return WindowFromPoint( pt32 );
/*******************************************************************
HWND WINAPI WindowFromPoint( POINT pt )

Alexandre Julliard
committed
INT hittest;
return WINPOS_WindowFromPoint( 0, pt, &hittest );
}
/*******************************************************************
HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
POINT pt32;
return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
}
/*******************************************************************
HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
/* pt is in the client coordinates */
WND* wnd = WIN_FindWndPtr(hwndParent);
RECT rect;
if( !wnd ) return 0;
/* get client rect fast */
rect.top = rect.left = 0;
rect.right = wnd->rectClient.right - wnd->rectClient.left;
rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
if (!PtInRect( &rect, pt ))
{
retvalue = 0;
goto end;
}
WIN_UpdateWndPtr(&wnd,wnd->child);
if (PtInRect( &wnd->rectWindow, pt ))
{
retvalue = wnd->hwndSelf;
goto end;
}
WIN_UpdateWndPtr(&wnd,wnd->next);
retvalue = hwndParent;
end:
WIN_ReleaseWndPtr(wnd);
return retvalue;
/*******************************************************************
*/
HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
{
POINT pt32;
CONV_POINT16TO32( &pt, &pt32 );
return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
}
/*******************************************************************
HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
UINT uFlags)
{
/* pt is in the client coordinates */
WND* wnd = WIN_FindWndPtr(hwndParent);
RECT rect;
if( !wnd ) return 0;
/* get client rect fast */
rect.top = rect.left = 0;
rect.right = wnd->rectClient.right - wnd->rectClient.left;
rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
if (!PtInRect( &rect, pt ))
{
retvalue = 0;
goto end;
}
WIN_UpdateWndPtr(&wnd,wnd->child);
while ( wnd )
{
if (PtInRect( &wnd->rectWindow, pt )) {
if ( (uFlags & CWP_SKIPINVISIBLE) &&
!(wnd->dwStyle & WS_VISIBLE) );
else if ( (uFlags & CWP_SKIPDISABLED) &&
(wnd->dwStyle & WS_DISABLED) );
else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
(wnd->dwExStyle & WS_EX_TRANSPARENT) );
{
retvalue = wnd->hwndSelf;
goto end;
}
WIN_UpdateWndPtr(&wnd,wnd->next);
retvalue = hwndParent;
end:
WIN_ReleaseWndPtr(wnd);
return retvalue;
/*******************************************************************
* WINPOS_GetWinOffset
*
* Calculate the offset between the origin of the two windows. Used
* to implement MapWindowPoints.
*/
static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
POINT *offset )
offset->x = offset->y = 0;
if (hwndFrom == hwndTo ) return;
ERR("bad hwndFrom = %04x\n",hwndFrom);
offset->x += wndPtr->rectClient.left;
offset->y += wndPtr->rectClient.top;
WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
WIN_ReleaseWndPtr(wndPtr);
}
/* Translate origin to destination window coords */
ERR("bad hwndTo = %04x\n", hwndTo );
offset->x -= wndPtr->rectClient.left;
offset->y -= wndPtr->rectClient.top;
WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
WIN_ReleaseWndPtr(wndPtr);
}
/*******************************************************************
void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
LPPOINT16 lppt, UINT16 count )
POINT offset;
WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
while (count--)
{
lppt->x += offset.x;
lppt->y += offset.y;
lppt++;
}
}
/*******************************************************************
INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
LPPOINT lppt, UINT count )
POINT offset;
WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
while (count--)
lppt->x += offset.x;
lppt->y += offset.y;
lppt++;
return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
}
/***********************************************************************
return IsIconic(hWnd);
/***********************************************************************
BOOL WINAPI IsIconic(HWND hWnd)
WND * wndPtr = WIN_FindWndPtr(hWnd);
if (wndPtr == NULL) return FALSE;
retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}
/***********************************************************************
return IsZoomed(hWnd);
/***********************************************************************
BOOL WINAPI IsZoomed(HWND hWnd)
WND * wndPtr = WIN_FindWndPtr(hWnd);
if (wndPtr == NULL) return FALSE;
retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
/*******************************************************************
return (HWND16)GetActiveWindow();
/*******************************************************************
HWND WINAPI GetActiveWindow(void)
MESSAGEQUEUE *pCurMsgQ = 0;
/* Get the messageQ for the current thread */
if (!(pCurMsgQ = QUEUE_Current()))
WARN("\tCurrent message queue not found. Exiting!\n" );
return 0;
}
/* Return the current active window from the perQ data of the current message Q */
return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
/*******************************************************************
static BOOL WINPOS_CanActivate(WND* pWnd)
if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
== WS_VISIBLE ) ) return TRUE;
/*******************************************************************
return SetActiveWindow(hwnd);
/*******************************************************************
HWND WINAPI SetActiveWindow( HWND hwnd )
HWND prev = 0;
MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
{
prev = 0;
goto end;
}
/* Get the messageQ for the current thread */
if (!(pCurMsgQ = QUEUE_Current()))
WARN("\tCurrent message queue not found. Exiting!\n" );
goto CLEANUP;
}
/* Retrieve the message queue associated with this window */
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
if ( !pMsgQ )
{
WARN("\tWindow message queue not found. Exiting!\n" );
goto CLEANUP;
}
/* Make sure that the window is associated with the calling threads
* message queue. It must share the same perQ data.
*/
if ( pCurMsgQ->pQData != pMsgQ->pQData )
goto CLEANUP;
/* Save current active window */
prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
CLEANUP:
/* Unlock the queues before returning */
if ( pMsgQ )
QUEUE_Unlock( pMsgQ );
end:
WIN_ReleaseWndPtr(wndPtr);
/*******************************************************************
*/
HWND16 WINAPI GetForegroundWindow16(void)
{
return (HWND16)GetForegroundWindow();
}
/*******************************************************************
*/
BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
{
return SetForegroundWindow( hwnd );
}
/*******************************************************************
HWND WINAPI GetForegroundWindow(void)
HWND hwndActive = 0;
/* Get the foreground window (active window of hActiveQueue) */
if ( hActiveQueue )
{
MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
if ( pActiveQueue )
hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
QUEUE_Unlock( pActiveQueue );
}
return hwndActive;
}
/*******************************************************************
BOOL WINAPI SetForegroundWindow( HWND hwnd )
return WINPOS_ChangeActiveWindow( hwnd, FALSE );
/*******************************************************************
*/
BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
{
/* FIXME: If Win98/2000 style SetForegroundWindow behavior is
* implemented, then fix this function. */
return TRUE;
}
/*******************************************************************
*/
BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
{
/* FIXME: If Win98/2000 style SetForegroundWindow behavior is
* implemented, then fix this function. */
return TRUE;
}
/*******************************************************************
return GetShellWindow();
/*******************************************************************
HWND WINAPI SetShellWindow(HWND hwndshell)
{ WARN("(hWnd=%08x) semi stub\n",hwndshell );
hGlobalShellWindow = hwndshell;
return hGlobalShellWindow;
/*******************************************************************
HWND WINAPI GetShellWindow(void)
{ WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
/***********************************************************************
return BringWindowToTop(hwnd);
/***********************************************************************
BOOL WINAPI BringWindowToTop( HWND hwnd )
return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
/***********************************************************************
BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
BOOL16 repaint )
{
return MoveWindow(hwnd,x,y,cx,cy,repaint);
/***********************************************************************
BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
BOOL repaint )
int flags = SWP_NOZORDER | SWP_NOACTIVATE;
if (!repaint) flags |= SWP_NOREDRAW;
TRACE("%04x %d,%d %dx%d %d\n",
return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
/***********************************************************************
* WINPOS_InitInternalPos