Skip to content
Snippets Groups Projects
winpos.c 39.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*
     * Window position related functions.
     *
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     * Copyright 1993, 1994, 1995 Alexandre Julliard
    
     *                       1995, 1996, 1999 Alex Korobka
    
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include <string.h>
    
    #include "winerror.h"
    
    #include "winerror.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "user.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "win.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "message.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "winpos.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "nonclient.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #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;
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /* ----- internal variables ----- */
    
    
    static HWND hGlobalShellWindow=0; /*the shell*/
    
    static HWND hGlobalTaskmanWindow=0;
    static HWND hGlobalProgmanWindow=0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    static LPCSTR atomInternalPos;
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /***********************************************************************
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     *           WINPOS_CreateInternalPosAtom
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINPOS_CreateInternalPosAtom()
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        LPSTR str = "SysIP";
    
        atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        return (atomInternalPos) ? TRUE : FALSE;
    }
    
    /***********************************************************************
     *           WINPOS_CheckInternalPos
     *
     * Called when a window is destroyed.
     */
    
    void WINPOS_CheckInternalPos( HWND hwnd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
        if( lpPos )
        {
    
    	if( IsWindow(lpPos->hwndIconTitle) )
    
    	    DestroyWindow( lpPos->hwndIconTitle );
    
    	HeapFree( GetProcessHeap(), 0, lpPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		ArrangeIconicWindows (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    UINT WINAPI ArrangeIconicWindows( HWND parent )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        RECT rectParent;
        HWND hwndChild;
        INT x, y, xspacing, yspacing;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        GetClientRect( parent, &rectParent );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        x = rectParent.left;
        y = rectParent.bottom;
    
        xspacing = GetSystemMetrics(SM_CXICONSPACING);
        yspacing = GetSystemMetrics(SM_CYICONSPACING);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        hwndChild = GetWindow( parent, GW_CHILD );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        while (hwndChild)
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            {
    
                WINPOS_ShowIconTitle( hwndChild, FALSE );
    
    
                SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
                                y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
    
                    WINPOS_ShowIconTitle(hwndChild , TRUE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                if (x <= rectParent.right - xspacing) x += xspacing;
                else
                {
                    x = rectParent.left;
                    y -= yspacing;
                }
            }
    
            hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
        return yspacing;
    }
    
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		SwitchToThisWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		GetWindowRect (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
    
        if (ret)
        {
            MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
    
            TRACE( "hwnd %p (%ld,%ld)-(%ld,%ld)\n",
    
                   hwnd, rect->left, rect->top, rect->right, rect->bottom);
        }
        return ret;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		GetWindowRgn (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
    {
        int nRet = ERROR;
    
        WND *wndPtr = WIN_GetPtr( hwnd );
    
        if (wndPtr == WND_OTHER_PROCESS)
        {
            if (IsWindow( hwnd ))
    
                FIXME( "not supported on other process window %p\n", hwnd );
    
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return ERROR;
    
        if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
        WIN_ReleasePtr( wndPtr );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    /***********************************************************************
    
     *		SetWindowRgn (USER32.@)
    
     */
    int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    
        if (hrgn) /* verify that region really exists */
        {
            if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE;
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if (USER_Driver.pSetWindowRgn)
            return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
    
                FIXME( "not supported on other process window %p\n", hwnd );
    
            wndPtr = NULL;
        }
        if (!wndPtr)
        {
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return FALSE;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
            WIN_ReleasePtr( wndPtr );
            return TRUE;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if (wndPtr->hrgnWnd)
        {
            /* delete previous region */
            DeleteObject(wndPtr->hrgnWnd);
            wndPtr->hrgnWnd = 0;
        }
        wndPtr->hrgnWnd = hrgn;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        /* 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) );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /***********************************************************************
    
     *		GetClientRect (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        rect->right = rect->bottom = 0;
        if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
    
            rect->right -= rect->left;
            rect->bottom -= rect->top;
    
        rect->left = rect->top = 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    }
    
    
    /*******************************************************************
    
     *		ClientToScreen (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        MapWindowPoints( hwnd, 0, lppnt, 1 );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        return TRUE;
    }
    
    
    /*******************************************************************
    
     *		ScreenToClient (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        MapWindowPoints( 0, hwnd, lppnt, 1 );
    
    /***********************************************************************
     *           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;
    
        LONG style, exstyle;
        RECT rectWindow, rectClient;
    
        WND *wndPtr;
        HWND *list = WIN_ListChildren( parent );
    
        HWND retvalue = 0;
    
    
        if (!list) return 0;
        for (i = 0; list[i]; i++)
        {
            /* 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.       */
    
    
            style = GetWindowLongW( list[i], GWL_STYLE );
            if (!(style & WS_VISIBLE)) continue;  /* not visible -> skip */
            if ((style & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
                continue;  /* disabled child -> skip */
            exstyle = GetWindowLongW( list[i], GWL_EXSTYLE );
            if ((exstyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
                continue;  /* transparent -> skip */
    
            if (!WIN_GetRectangles( list[i], &rectWindow, &rectClient )) continue;
            if (!PtInRect( &rectWindow, pt )) continue;  /* not in window -> skip */
    
            /* FIXME: check window region for other processes too */
            if ((wndPtr = WIN_GetPtr( list[i] )) && wndPtr != WND_OTHER_PROCESS)
    
                if (wndPtr->hrgnWnd && !PtInRegion( wndPtr->hrgnWnd,
                                                    pt.x - rectWindow.left, pt.y - rectWindow.top ))
                {
                    WIN_ReleasePtr( wndPtr );
                    continue;  /* point outside window region -> skip */
                }
                WIN_ReleasePtr( wndPtr );
    
            }
    
            /* If window is minimized or disabled, return at once */
    
            if (style & WS_MINIMIZE)
    
                retvalue = list[i];
                break;
    
            if (style & WS_DISABLED)
    
                retvalue = list[i];
                break;
    
            }
    
            /* If point is in client area, explore children */
    
            if (PtInRect( &rectClient, pt ))
    
                new_pt.x = pt.x - rectClient.left;
                new_pt.y = pt.y - rectClient.top;
    
                if ((retvalue = find_child_from_point( list[i], new_pt, hittest, lparam ))) break;
    
            }
    
            /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
            if (!WIN_IsCurrentThread( list[i] ))
            {
                *hittest = HTCLIENT;
    
                retvalue = list[i];
                break;
    
            }
            if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
            {
                *hittest = res;  /* Found the window */
    
                retvalue = list[i];
                break;
    
            /* continue search with next sibling */
    
        HeapFree( GetProcessHeap(), 0, list );
        return retvalue;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
     *           WINPOS_WindowFromPoint
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     *
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     * Find the window and hittest for a given point.
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        TRACE("scope %p %ld,%ld\n", hwndScope, pt.x, pt.y);
    
    
        if (!hwndScope) hwndScope = GetDesktopWindow();
    
        style = GetWindowLongW( hwndScope, GWL_STYLE );
    
        if (style & WS_DISABLED) return 0;
    
        MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope, GA_PARENT ), &xy, 1 );
    
        if (!(style & WS_MINIMIZE))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
            RECT rectClient;
            if (WIN_GetRectangles( hwndScope, NULL, &rectClient ) && PtInRect( &rectClient, xy ))
    
                HWND ret;
    
                xy.x -= rectClient.left;
                xy.y -= rectClient.top;
                if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
                {
    
                    TRACE( "found child %p\n", ret );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
        /* If nothing found, try the scope window */
        if (!WIN_IsCurrentThread( hwndScope ))
        {
            *hittest = HTCLIENT;
    
            TRACE( "returning %p\n", hwndScope );
    
            return hwndScope;
        }
        res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
        if (res != HTTRANSPARENT)
        {
            *hittest = res;  /* Found the window */
    
            TRACE( "returning %p\n", hwndScope );
    
            return hwndScope;
        }
        *hittest = HTNOWHERE;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		WindowFromPoint (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI WindowFromPoint( POINT pt )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        INT hittest;
        return WINPOS_WindowFromPoint( 0, pt, &hittest );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		ChildWindowFromPoint (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
    
    /*******************************************************************
    
     *		ChildWindowFromPointEx (USER32.@)
    
    HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
    
    {
        /* pt is in the client coordinates */
    
        HWND retvalue;
    
        GetClientRect( hwndParent, &rect );
        if (!PtInRect( &rect, pt )) return 0;
    
        if (!(list = WIN_ListChildren( hwndParent ))) return 0;
    
        for (i = 0; list[i]; i++)
    
            if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
            if (!PtInRect( &rect, pt )) continue;
            if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
            {
                LONG style = GetWindowLongW( list[i], GWL_STYLE );
                if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
                if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
            }
            if (uFlags & CWP_SKIPTRANSPARENT)
    
                if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
    
        retvalue = list[i];
    
        HeapFree( GetProcessHeap(), 0, list );
    
        if (!retvalue) retvalue = hwndParent;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /*******************************************************************
     *         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 )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        offset->x = offset->y = 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        /* Translate source window origin to screen coords */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if (hwndFrom)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            {
    
                if (hwnd == hwndTo) return;
                if (!(wndPtr = WIN_GetPtr( hwnd )))
    
                    ERR( "bad hwndFrom = %p\n", hwnd );
    
                if (wndPtr == WND_OTHER_PROCESS) goto other_process;
                offset->x += wndPtr->rectClient.left;
                offset->y += wndPtr->rectClient.top;
                hwnd = wndPtr->parent;
                WIN_ReleasePtr( wndPtr );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
    
        /* Translate origin to destination window coords */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if (hwndTo)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            {
    
                if (!(wndPtr = WIN_GetPtr( hwnd )))
    
                    ERR( "bad hwndTo = %p\n", hwnd );
    
                if (wndPtr == WND_OTHER_PROCESS) goto other_process;
                offset->x -= wndPtr->rectClient.left;
                offset->y -= wndPtr->rectClient.top;
                hwnd = wndPtr->parent;
                WIN_ReleasePtr( wndPtr );
            }
        }
        return;
    
     other_process:  /* one of the parents may belong to another process, do it the hard way */
        offset->x = offset->y = 0;
        SERVER_START_REQ( get_windows_offset )
        {
            req->from = hwndFrom;
            req->to   = hwndTo;
    
                offset->x = reply->x;
                offset->y = reply->y;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    }
    
    
    /*******************************************************************
    
     *		MapWindowPoints (USER.258)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
                                   LPPOINT16 lppt, UINT16 count )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        while (count--)
        {
    	lppt->x += offset.x;
    	lppt->y += offset.y;
            lppt++;
        }
    }
    
    
    /*******************************************************************
    
     *		MapWindowPoints (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        while (count--)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	lppt->x += offset.x;
    	lppt->y += offset.y;
            lppt++;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
        return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		IsIconic (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		IsZoomed (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
    
    /*******************************************************************
    
     *		AllowSetForegroundWindow (USER32.@)
    
     */
    BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
    {
        /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
         * implemented, then fix this function. */
        return TRUE;
    }
    
    
    /*******************************************************************
    
     *		LockSetForegroundWindow (USER32.@)
    
     */
    BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
    {
        /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
         * implemented, then fix this function. */
        return TRUE;
    }
    
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		SetShellWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI SetShellWindow(HWND hwndshell)
    
    {   WARN("(hWnd=%p) semi stub\n",hwndshell );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        return hGlobalShellWindow;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /*******************************************************************
    
     *		GetShellWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    {   WARN("(hWnd=%p) semi stub\n",hGlobalShellWindow );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
        return hGlobalShellWindow;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		BringWindowToTop (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI BringWindowToTop( HWND hwnd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		MoveWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
                                BOOL repaint )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        int flags = SWP_NOZORDER | SWP_NOACTIVATE;
        if (!repaint) flags |= SWP_NOREDRAW;
    
        TRACE("%p %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
    
        return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    }
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
     *           WINPOS_InitInternalPos
     */
    
    static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                                                          atomInternalPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if( !lpPos )
        {
    
    	/* this happens when the window is minimized/maximized
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	 * for the first time (rectWindow is not adjusted yet) */
    
    
    	lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	if( !lpPos ) return NULL;
    
    
    	SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
    
    	*(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
    
        if( wnd->dwStyle & WS_MINIMIZE )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
    
        else if( wnd->dwStyle & WS_MAXIMIZE )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
    
        else if( restoreRect )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
        return lpPos;
    }
    
    /***********************************************************************
     *           WINPOS_RedrawIconTitle
     */
    
    BOOL WINPOS_RedrawIconTitle( HWND hWnd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if( lpPos )
        {
    	if( lpPos->hwndIconTitle )
    	{
    
    	    SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
    	    InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	    return TRUE;
    	}
        }
        return FALSE;
    }
    
    /***********************************************************************
     *           WINPOS_ShowIconTitle
     */
    
    BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    	TRACE("%p %i\n", hwnd, (bShow != 0) );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    	if( !title )
    	    lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	if( bShow )
            {
    
                if (!IsWindowVisible(title))
                {
                    SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
                    SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
                                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
                }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	}
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
        return FALSE;
    }
    
    /*******************************************************************
     *           WINPOS_GetMinMaxInfo
     *
     * Get the minimized and maximized information for a window.
     */
    
    void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
    
    			   POINT *minTrack, POINT *maxTrack )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
        LPINTERNALPOS lpPos;
    
        LONG style = GetWindowLongA( hwnd, GWL_STYLE );
        LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        /* Compute default values */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
        MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
        MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
        MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
        MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
        MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if (HAS_DLGFRAME( style, exstyle ))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
            xinc = GetSystemMetrics(SM_CXDLGFRAME);
            yinc = GetSystemMetrics(SM_CYDLGFRAME);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
        else
        {
            xinc = yinc = 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            {
    
                xinc += GetSystemMetrics(SM_CXFRAME);
                yinc += GetSystemMetrics(SM_CYFRAME);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            {
    
                xinc += GetSystemMetrics(SM_CXBORDER);
                yinc += GetSystemMetrics(SM_CYBORDER);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        MinMax.ptMaxSize.x += 2 * xinc;
        MinMax.ptMaxSize.y += 2 * yinc;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        else
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
            MinMax.ptMaxPosition.x = -xinc;
            MinMax.ptMaxPosition.y = -yinc;
    
        SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
          /* Some sanity checks */
    
    
        TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                          MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
                          MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
                          MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
                          MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
    
        MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                                       MinMax.ptMinTrackSize.x );
    
        MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
                                       MinMax.ptMinTrackSize.y );
    
        if (maxSize) *maxSize = MinMax.ptMaxSize;
        if (maxPos) *maxPos = MinMax.ptMaxPosition;
        if (minTrack) *minTrack = MinMax.ptMinTrackSize;
        if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		ShowWindowAsync (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     *
     * doesn't wait; returns immediately.
     * used by threads to toggle windows in other (possibly hanging) threads
     */
    
    BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        HWND full_handle;
    
    
        if (is_broadcast(hwnd))
        {
            SetLastError( ERROR_INVALID_PARAMETER );
            return FALSE;
        }
    
    
        if ((full_handle = WIN_IsCurrentThread( hwnd )))
            return USER_Driver.pShowWindow( full_handle, cmd );
        return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		ShowWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
    {
    
        if (is_broadcast(hwnd))
        {
            SetLastError( ERROR_INVALID_PARAMETER );
            return FALSE;
        }
    
        if ((full_handle = WIN_IsCurrentThread( hwnd )))
    
        {
            if (USER_Driver.pShowWindow)
                return USER_Driver.pShowWindow( full_handle, cmd );
            return FALSE;
        }
    
        return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		GetInternalWindowPos (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
                                          LPPOINT ptIcon )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        WINDOWPLACEMENT wndpl;
        if (GetWindowPlacement( hwnd, &wndpl ))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    	if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
    	if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
    	return wndpl.showCmd;
        }
        return 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /***********************************************************************
    
     *		GetWindowPlacement (USER32.@)
    
     *
     * Win95:
     * Fails if wndpl->length of Win95 (!) apps is invalid.
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        WND *pWnd = WIN_FindWndPtr( hwnd );
        LPINTERNALPOS lpPos;
    
        if(!pWnd ) return FALSE;
    
        lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
        wndpl->length  = sizeof(*wndpl);
        if( pWnd->dwStyle & WS_MINIMIZE )
            wndpl->showCmd = SW_SHOWMINIMIZED;
        else
            wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
        if( pWnd->flags & WIN_RESTORE_MAX )
            wndpl->flags = WPF_RESTORETOMAXIMIZED;
        else
            wndpl->flags = 0;
        CONV_POINT16TO32( &lpPos->ptIconPos, &wndpl->ptMinPosition );
        CONV_POINT16TO32( &lpPos->ptMaxPos, &wndpl->ptMaxPosition );
        CONV_RECT16TO32( &lpPos->rectNormal, &wndpl->rcNormalPosition );
        WIN_ReleaseWndPtr(pWnd);
        return TRUE;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    }
    
    
    /***********************************************************************
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     *           WINPOS_SetPlacement
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        WND *pWnd = WIN_FindWndPtr( hwnd );
        if( pWnd )
        {
    	LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
    
    			     *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    	if( flags & PLACE_MIN ) CONV_POINT32TO16( &wndpl->ptMinPosition, &lpPos->ptIconPos );
    	if( flags & PLACE_MAX ) CONV_POINT32TO16( &wndpl->ptMaxPosition, &lpPos->ptMaxPos );
    	if( flags & PLACE_RECT) CONV_RECT32TO16( &wndpl->rcNormalPosition, &lpPos->rectNormal );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    	if( pWnd->dwStyle & WS_MINIMIZE )
    	{
    
    	    WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	    if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
    
    		SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    				0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	else if( pWnd->dwStyle & WS_MAXIMIZE )
    	{
    	    if( !EMPTYPOINT(lpPos->ptMaxPos) )
    
    		SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    				0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
    	}
    	else if( flags & PLACE_RECT )
    
    		SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    				lpPos->rectNormal.right - lpPos->rectNormal.left,
    				lpPos->rectNormal.bottom - lpPos->rectNormal.top,
    				SWP_NOZORDER | SWP_NOACTIVATE );
    
    
    	ShowWindow( hwnd, wndpl->showCmd );
    	if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	{
    
    	    if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    	    /* SDK: ...valid only the next time... */
    	    if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
    	}
    
            WIN_ReleaseWndPtr(pWnd);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	return TRUE;
        }
        return FALSE;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /***********************************************************************
    
     *		SetWindowPlacement (USER32.@)
    
     *
     * Win95:
     * Fails if wndpl->length of Win95 (!) apps is invalid.
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        if (!wpl) return FALSE;
        return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
    
    /***********************************************************************
     *		AnimateWindow (USER32.@)
     *		Shows/Hides a window with an animation
     *		NO ANIMATION YET
     */
    BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
    {
    	FIXME("partial stub\n");
    
    	/* If trying to show/hide and it's already   *
    	 * shown/hidden or invalid window, fail with *
    	 * invalid parameter                         */
    	if(!IsWindow(hwnd) ||
    	   (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
    	   (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
    	{
    		SetLastError(ERROR_INVALID_PARAMETER);
    		return FALSE;