Skip to content
Snippets Groups Projects
winpos.c 49.6 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
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include <string.h>
    
    #include "winerror.h"
    
    #include "windef.h"
    #include "wingdi.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 "hook.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "message.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "queue.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "winpos.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "dce.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 hwndPrevActive  = 0;  /* Previously active window */
    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;
        MESSAGEQUEUE *pMsgQ = 0;
    
        WND *wndPtr = WIN_GetPtr( hwnd );
    
        if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
    
        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" );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
        if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
    
    
        if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
            PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
    
    	WARN("\tattempt to activate destroyed window!\n");
    
    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
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if (!wndPtr) return FALSE;
    
    
        if (wndPtr != WND_OTHER_PROCESS)
        {
            *rect = wndPtr->rectWindow;
            WIN_ReleasePtr( wndPtr );
            ret = TRUE;
        }
        else
        {
            SERVER_START_REQ( get_window_rectangles )
            {
                req->handle = hwnd;
                if ((ret = !SERVER_CALL_ERR()))
                {
                    rect->left   = req->window.left;
                    rect->top    = req->window.top;
                    rect->right  = req->window.right;
                    rect->bottom = req->window.bottom;
                }
            }
            SERVER_END_REQ;
        }
        if (ret)
        {
            MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
            TRACE( "hwnd %04x (%d,%d)-(%d,%d)\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 %x\n", hwnd );
            wndPtr = NULL;
        }
        if (!wndPtr)
    
            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)
    
            if (IsWindow( hwnd ))
                FIXME( "not supported on other process window %x\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
    {
    
        BOOL ret;
        WND *wndPtr = WIN_GetPtr( hwnd );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
        rect->left = rect->top = rect->right = rect->bottom = 0;
    
        if (!wndPtr) return FALSE;
    
        if (wndPtr != WND_OTHER_PROCESS)
        {
            rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
            rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
            WIN_ReleasePtr( wndPtr );
            ret = TRUE;
        }
        else
        {
            SERVER_START_REQ( get_window_rectangles )
            {
                req->handle = hwnd;
                if ((ret = !SERVER_CALL_ERR()))
                {
                    rect->right  = req->client.right - req->client.left;
                    rect->bottom = req->client.bottom - req->client.top;
                }
            }
            SERVER_END_REQ;
        }
        return ret;
    
    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;
        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 */
    
            /* 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;
    }
    
    
    
    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 %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
    
        if (!hwndScope) hwndScope = GetDesktopWindow();
        if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
    
        hwndScope = wndScope->hwndSelf;  /* make it a full handle */
    
        if( wndScope->dwStyle & WS_DISABLED )
        {
    
            WIN_ReleaseWndPtr(wndScope);
            return 0;
    
            MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
    
        if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
            xy.x -= wndScope->rectClient.left;
            xy.y -= wndScope->rectClient.top;
            WIN_ReleaseWndPtr( wndScope );
            if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
        else WIN_ReleaseWndPtr( wndScope );
    
        /* If nothing found, try the scope window */
        if (!WIN_IsCurrentThread( hwndScope ))
        {
            *hittest = HTCLIENT;
    
            TRACE( "returning %x\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 %x\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 */
    
        GetClientRect( hwndParent, &rect );
        if (!PtInRect( &rect, pt )) return 0;
    
        if (!(list = WIN_ListChildren( hwndParent ))) return 0;
    
        for (i = 0; list[i] && !retvalue; i++)
    
            WND *wnd = WIN_FindWndPtr( list[i] );
            if (!wnd) continue;
            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) );
                else retvalue = list[i];
            }
            WIN_ReleaseWndPtr( wnd );
    
        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 = %04x\n", hwnd );
                    return;
    
                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 = %04x\n", hwnd );
                    return;
    
                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;
            if (!SERVER_CALL())
            {
                offset->x = req->x;
                offset->y = req->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;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		GetActiveWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI GetActiveWindow(void)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        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 );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     *         WINPOS_CanActivate
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    static BOOL WINPOS_CanActivate(HWND hwnd)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        if (!hwnd) return FALSE;
        return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_VISIBLE|WS_CHILD)) == WS_VISIBLE);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		SetActiveWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI SetActiveWindow( HWND hwnd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        WND *wndPtr = WIN_FindWndPtr( hwnd );
    
        MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        if (!wndPtr) return 0;
    
        if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
        /* Get the messageQ for the current thread */
    
        if (!(pCurMsgQ = QUEUE_Current()))
    
            WARN("\tCurrent message queue not found. Exiting!\n" );
    
        /* Retrieve the message queue associated with this window */
        pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
        if ( !pMsgQ )
        {
    
            WARN("\tWindow message queue not found. Exiting!\n" );
    
        }
    
        /* 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 )
    
        /* Save current active window */
        prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
    
        QUEUE_Unlock( pMsgQ );
        WIN_ReleaseWndPtr(wndPtr);
    
        WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
    
        WIN_ReleaseWndPtr(wndPtr);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /*******************************************************************
    
     *		GetForegroundWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    HWND WINAPI GetForegroundWindow(void)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        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 );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    
            QUEUE_Unlock( pActiveQueue );
        }
    
        return hwndActive;
    }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    
    /*******************************************************************
    
     *		SetForegroundWindow (USER32.@)
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
     */
    
    BOOL WINAPI SetForegroundWindow( HWND hwnd )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
    
        if (!hwnd) return WINPOS_SetActiveWindow( 0, FALSE, TRUE );
    
        /* child windows get WM_CHILDACTIVATE message */
        if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
            return SendMessageA( hwnd, WM_CHILDACTIVATE, 0, 0 );
    
        hwnd = WIN_GetFullHandle( hwnd );
        if( hwnd == GetForegroundWindow() ) return FALSE;
    
        return WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
    
    /*******************************************************************
    
     *		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=%08x) 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=%x) 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
    {    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        int flags = SWP_NOZORDER | SWP_NOACTIVATE;
        if (!repaint) flags |= SWP_NOREDRAW;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	    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 
    	 * 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;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        }
    
        if( wnd->dwStyle & WS_MINIMIZE ) 
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        else if( wnd->dwStyle & WS_MAXIMIZE ) 
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        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("0x%04x %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;