Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

win32wbasepos.cpp

Go to the documentation of this file.
00001 /* $Id: win32wbasepos.cpp,v 1.26 2001/06/09 14:50:22 sandervl Exp $ */
00002 /*
00003  * Win32 Window Base Class for OS/2 (nonclient/position methods)
00004  *
00005  * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
00006  * Copyright 1999      Daniela Engert (dani@ngrt.de)
00007  *
00008  * Parts based on Wine Windows code (windows\win.c, windows\nonclient.c)
00009  *
00010  * Copyright 1993, 1994 Alexandre Julliard
00011  *
00012  * TODO: Not thread/process safe
00013  *
00014  * Wine code based on build 990815
00015  *
00016  * Project Odin Software License can be found in LICENSE.TXT
00017  *
00018  */
00019 #include <os2win.h>
00020 #include <win.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <stdarg.h>
00024 #include <assert.h>
00025 #include <misc.h>
00026 #include <win32wbase.h>
00027 #include <spy.h>
00028 #include "wndmsg.h"
00029 #include "oslibwin.h"
00030 #include "oslibutil.h"
00031 #include "oslibgdi.h"
00032 #include "oslibres.h"
00033 #include "oslibdos.h"
00034 #include "syscolor.h"
00035 #include "win32wndhandle.h"
00036 #include "dc.h"
00037 #include "win32wdesktop.h"
00038 #include <win\hook.h>
00039 
00040 #define DBG_LOCALLOG    DBG_win32wbasepos
00041 #include "dbglocal.h"
00042 
00043 /*******************************************************************
00044  *           GetMinMaxInfo
00045  *
00046  * Get the minimized and maximized information for a window.
00047  */
00048 void Win32BaseWindow::GetMinMaxInfo(POINT *maxSize, POINT *maxPos,
00049                                     POINT *minTrack, POINT *maxTrack )
00050 {
00051     MINMAXINFO MinMax;
00052     INT xinc, yinc;
00053 
00054     /* Compute default values */
00055     MinMax.ptMaxPosition.x = 0;
00056     MinMax.ptMaxPosition.y = 0;
00057 
00058     if(!(getStyle() & (WS_POPUP | WS_CHILD))) {
00059         RECT rect;
00060         OSLibWinGetMaxPosition(getOS2FrameWindowHandle(), &rect);
00061         MinMax.ptMaxPosition.x = rect.left;
00062         MinMax.ptMaxPosition.y = rect.top;
00063 
00064         MinMax.ptMaxSize.x = rect.right - rect.left;
00065         MinMax.ptMaxSize.y = rect.bottom - rect.top;
00066         MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
00067         MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
00068         MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
00069         MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
00070     }
00071     else {
00072         MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
00073         MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
00074         MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
00075         MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
00076         MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
00077         MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
00078     }
00079 
00080     if (HAS_DLGFRAME( dwStyle, dwExStyle ))
00081     {
00082         xinc = GetSystemMetrics(SM_CXDLGFRAME);
00083         yinc = GetSystemMetrics(SM_CYDLGFRAME);
00084     }
00085     else
00086     {
00087         xinc = yinc = 0;
00088         if (HAS_THICKFRAME(dwStyle, dwExStyle))
00089         {
00090             xinc += GetSystemMetrics(SM_CXFRAME);
00091             yinc += GetSystemMetrics(SM_CYFRAME);
00092         }
00093         //SvL: Wine has no 'else', but I'm seeing different behaviour in NT
00094         //     and it doesn't make much sense either as a window can have
00095         //     only one kind of border (see drawing code)
00096         else
00097         if (dwStyle & WS_BORDER)
00098         {
00099             xinc += GetSystemMetrics(SM_CXBORDER);
00100             yinc += GetSystemMetrics(SM_CYBORDER);
00101         }
00102     }
00103     MinMax.ptMaxSize.x += 2 * xinc;
00104     MinMax.ptMaxSize.y += 2 * yinc;
00105 
00106 #if 0
00107     lpPos = (LPINTERNALPOS)GetPropA( hwndSelf, atomInternalPos );
00108     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
00109         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
00110     else
00111     {
00112 #endif
00113         MinMax.ptMaxPosition.x -= xinc;
00114         MinMax.ptMaxPosition.y -= yinc;
00115 //    }
00116 
00117     SendInternalMessageA(WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
00118 
00119       /* Some sanity checks */
00120 
00121     dprintf(("GetMinMaxInfo: %ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
00122                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
00123                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
00124                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
00125                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y));
00126     MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
00127                                    MinMax.ptMinTrackSize.x );
00128     MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
00129                                    MinMax.ptMinTrackSize.y );
00130 
00131     if (maxSize)    *maxSize  = MinMax.ptMaxSize;
00132     if (maxPos)     *maxPos   = MinMax.ptMaxPosition;
00133     if (minTrack)   *minTrack = MinMax.ptMinTrackSize;
00134     if (maxTrack)   *maxTrack = MinMax.ptMaxTrackSize;
00135 }
00136 /***********************************************************************
00137  *           WINPOS_SendNCCalcSize
00138  *
00139  * Send a WM_NCCALCSIZE message to a window.
00140  * All parameters are read-only except newClientRect.
00141  * oldWindowRect, oldClientRect and winpos must be non-NULL only
00142  * when calcValidRect is TRUE.
00143  */
00144 LONG Win32BaseWindow::SendNCCalcSize(BOOL calcValidRect, RECT *newWindowRect,
00145                                      RECT *oldWindowRect,
00146                                      RECT *oldClientRect, WINDOWPOS *winpos,
00147                                      RECT *newClientRect )
00148 {
00149    NCCALCSIZE_PARAMS params;
00150    WINDOWPOS winposCopy;
00151    LONG result = 0;
00152 
00153    /* Send WM_NCCALCSIZE message to get new client area */
00154    params.rgrc[0] = *newWindowRect;
00155    if(calcValidRect)
00156    {
00157         winposCopy = *winpos;
00158         params.rgrc[1] = *oldWindowRect;
00159         params.rgrc[2] = *oldClientRect;
00160         //client rectangel must be in parent coordinates
00161         OffsetRect(&params.rgrc[2], rectWindow.left, rectWindow.top);
00162 
00163         params.lppos = &winposCopy;
00164    }
00165    result = SendInternalMessageA(WM_NCCALCSIZE, calcValidRect, (LPARAM)&params );
00166 
00167    /* If the application send back garbage, ignore it */
00168    if(params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
00169    {
00170         *newClientRect = params.rgrc[0];
00171         //client rectangle now in parent coordinates; convert to 'frame' coordinates
00172         OffsetRect(newClientRect, -rectWindow.left, -rectWindow.top);
00173    }
00174 
00175    /* FIXME: WVR_ALIGNxxx */
00176    if(newClientRect->left != rectClient.left || newClientRect->top  != rectClient.top)
00177         winpos->flags &= ~SWP_NOCLIENTMOVE;
00178 
00179    if((newClientRect->right - newClientRect->left != rectClient.right - rectClient.left) ||
00180        (newClientRect->bottom - newClientRect->top != rectClient.bottom - rectClient.top))
00181         winpos->flags &= ~SWP_NOCLIENTSIZE;
00182 
00183    return result;
00184 }
00185 /***********************************************************************
00186  *           WINPOS_HandleWindowPosChanging
00187  *
00188  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
00189  */
00190 LONG Win32BaseWindow::HandleWindowPosChanging(WINDOWPOS *winpos)
00191 {
00192     POINT maxSize;
00193     if (winpos->flags & SWP_NOSIZE) return 0;
00194 
00195     if ((dwStyle & WS_THICKFRAME) ||
00196         ((dwStyle & (WS_POPUP | WS_CHILD)) == 0))
00197     {
00198         GetMinMaxInfo( &maxSize, NULL, NULL, NULL );
00199         winpos->cx = MIN( winpos->cx, maxSize.x );
00200         winpos->cy = MIN( winpos->cy, maxSize.y );
00201     }
00202     return 0;
00203 }
00204 /***********************************************************************
00205  *           WINPOS_FindIconPos
00206  *
00207  * Find a suitable place for an iconic window.
00208  */
00209 static void WINPOS_FindIconPos( HWND hwnd, POINT &pt )
00210 {
00211     RECT rectParent;
00212     int  x, y, xspacing, yspacing;
00213     HWND hwndChild, hwndParent;
00214 
00215     hwndParent = GetParent(hwnd);
00216     if(hwndParent == 0) {
00217         dprintf(("WINPOS_FindIconPos: no parent found for window %x", hwnd));
00218         return;
00219     }
00220 
00221     GetClientRect(hwndParent, &rectParent );
00222     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
00223         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
00224         return;  /* The icon already has a suitable position */
00225 
00226     xspacing = GetSystemMetrics(SM_CXICONSPACING);
00227     yspacing = GetSystemMetrics(SM_CYICONSPACING);
00228 
00229     y = rectParent.bottom;
00230     for (;;)
00231     {
00232         x = rectParent.left;
00233         do
00234         {
00235             /* Check if another icon already occupies this spot */
00236             hwndChild = GetWindow(hwndParent, GW_CHILD);
00237 
00238             while(hwndChild)
00239             {
00240                 Win32BaseWindow *child = NULL;
00241                 RECT *pRectWindow;
00242 
00243                 child = Win32BaseWindow::GetWindowFromHandle(hwndChild);
00244                 if(!child) {
00245                     dprintf(("ERROR: WINPOS_FindIconPos, child %x not found", hwndChild));
00246                     return;
00247                 }
00248                 if ((child->getStyle() & WS_MINIMIZE) && (child->getWindowHandle() != hwnd))
00249                 {
00250                     pRectWindow = child->getWindowRect();
00251                     if ((pRectWindow->left   < x + xspacing) &&
00252                         (pRectWindow->right  >= x) &&
00253                         (pRectWindow->top    <= y) &&
00254                         (pRectWindow->bottom > y - yspacing))
00255                         break;  /* There's a window in there */
00256                 }
00257                 RELEASE_WNDOBJ(child);
00258                 hwndChild = GetWindow(hwndChild, GW_HWNDNEXT);
00259             }
00260 
00261             if (!hwndChild) /* No window was found, so it's OK for us */
00262             {
00263                 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
00264                 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
00265                 return;
00266             }
00267             x += xspacing;
00268         } while(x <= rectParent.right-xspacing);
00269 
00270         y -= yspacing;
00271     }
00272 }
00273 /******************************************************************************
00274  *           WINPOS_MinMaximize
00275  *
00276  * Fill in lpRect and return additional flags to be used with SetWindowPos().
00277  * This function assumes that 'cmd' is different from the current window
00278  * state.
00279  */
00280 UINT Win32BaseWindow::MinMaximize(UINT cmd, LPRECT lpRect)
00281 {
00282     UINT swpFlags = 0;
00283     POINT size, iconPos;
00284 
00285     size.x = rectWindow.left;
00286     size.y = rectWindow.top;
00287 
00288     if(IsRectEmpty(&windowpos.rcNormalPosition)) {
00289         CopyRect(&windowpos.rcNormalPosition, &rectWindow);
00290     }
00291     if(!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, getWindowHandle(), cmd))
00292     {
00293         if(getStyle() & WS_MINIMIZE )
00294         {
00295             if(!SendInternalMessageA(WM_QUERYOPEN, 0, 0L))
00296                 return (SWP_NOSIZE | SWP_NOMOVE);
00297         }
00298         switch( cmd )
00299         {
00300         case SW_MINIMIZE:
00301             if( getStyle() & WS_MAXIMIZE)
00302             {
00303                  setFlags(getFlags() | WIN_RESTORE_MAX);
00304                  setStyle(getStyle() & ~WS_MAXIMIZE);
00305             }
00306             else setFlags(getFlags() & ~WIN_RESTORE_MAX);
00307 
00308             setStyle(getStyle() | WS_MINIMIZE);
00309 
00310             if(getParent() == NULL) {
00311                 SetRect(lpRect, -32000, -32000, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
00312                 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
00313             }
00314             else {
00315                 iconPos.x = windowpos.ptMinPosition.x;
00316                 iconPos.y = windowpos.ptMinPosition.y;
00317                 WINPOS_FindIconPos(getWindowHandle(), iconPos);
00318                 SetRect(lpRect, iconPos.x, iconPos.y, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
00319             }
00320             break;
00321 
00322         case SW_MAXIMIZE:
00323             GetMinMaxInfo(&size, &windowpos.ptMaxPosition, NULL, NULL );
00324 
00325             if(getStyle() & WS_MINIMIZE )
00326             {
00327                 setStyle(getStyle() & ~WS_MINIMIZE);
00328                 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
00329             }
00330             setStyle(getStyle() | WS_MAXIMIZE);
00331 
00332             SetRect(lpRect, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
00333                     size.x, size.y );
00334             break;
00335 
00336         case SW_RESTORE:
00337             if(getStyle() & WS_MINIMIZE)
00338             {
00339                 setStyle(getStyle() & ~WS_MINIMIZE);
00340                 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
00341 
00342                 if( getFlags() & WIN_RESTORE_MAX)
00343                 {
00344                     /* Restore to maximized position */
00345                     GetMinMaxInfo(&size, &windowpos.ptMaxPosition, NULL, NULL);
00346                     setStyle(getStyle() | WS_MAXIMIZE);
00347                     SetRect(lpRect, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y, size.x, size.y);
00348                     break;
00349                 }
00350             }
00351             else
00352             if( !(getStyle() & WS_MAXIMIZE) )
00353                  return 0;
00354             else setStyle(getStyle() & ~WS_MAXIMIZE);
00355 
00356             /* Restore to normal position */
00357             *lpRect = windowpos.rcNormalPosition;
00358             lpRect->right -= lpRect->left;
00359             lpRect->bottom -= lpRect->top;
00360             break;
00361         }
00362     }
00363     else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
00364 
00365     return swpFlags;
00366 }
00367 //******************************************************************************
00368 //******************************************************************************

Generated on Wed Jan 23 23:17:48 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001