Back to index

lightning-sunbird  0.9+nobinonly
nsFrameWindow.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Mozilla OS/2 libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * John Fairhurst, <john_fairhurst@iname.com>.
00018  * Portions created by the Initial Developer are Copyright (C) 1999
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Rich Walsh <dragtext@e-vertise.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK *****
00037  *
00038  * This Original Code has been modified by IBM Corporation.
00039  * Modifications made by IBM described herein are
00040  * Copyright (c) International Business Machines
00041  * Corporation, 2000
00042  *
00043  * Modifications to Mozilla code or documentation
00044  * identified per MPL Section 3.3
00045  *
00046  * Date             Modified by     Description of modification
00047  * 03/23/2000       IBM Corp.      Fix missing title bars on profile wizard windows.
00048  * 04/11/2000       IBM Corp.      Remove assertion.
00049  * 05/10/2000       IBM Corp.      Correct initial position of frame w/titlebar
00050  * 06/21/2000       IBM Corp.      Use rollup listener from nsWindow
00051  */
00052 
00053 // Frame window - produced when NS_WINDOW_CID is required.
00054 
00055 #include "nsFrameWindow.h"
00056 #include "nsIRollupListener.h"
00057 #include "nsIDeviceContext.h"
00058 #include "nsIComponentManager.h"
00059 #include "nsGfxCIID.h"
00060 
00061 extern nsIRollupListener * gRollupListener;
00062 extern nsIWidget         * gRollupWidget;
00063 extern PRBool              gRollupConsumeRollupEvent;
00064 
00065 #ifdef DEBUG_FOCUS
00066   extern int currentWindowIdentifier;
00067 #endif
00068 
00069 nsFrameWindow::nsFrameWindow() : nsWindow()
00070 {
00071    fnwpDefFrame = 0;
00072    mWindowType  = eWindowType_toplevel;
00073 }
00074 
00075 nsFrameWindow::~nsFrameWindow()
00076 {
00077 }
00078 
00079 void nsFrameWindow::SetWindowListVisibility( PRBool bState)
00080 {
00081    HSWITCH hswitch;
00082    SWCNTRL swctl;
00083 
00084    hswitch = WinQuerySwitchHandle(mFrameWnd, 0);
00085    if( hswitch)
00086    {
00087       WinQuerySwitchEntry( hswitch, &swctl);
00088       swctl.uchVisibility = bState ? SWL_VISIBLE : SWL_INVISIBLE;
00089       swctl.fbJump        = bState ? SWL_JUMPABLE : SWL_NOTJUMPABLE;
00090       WinChangeSwitchEntry( hswitch, &swctl);
00091    }
00092 }
00093 
00094 // Called in the PM thread.
00095 void nsFrameWindow::RealDoCreate( HWND hwndP, nsWindow *aParent,
00096                                   const nsRect &aRect,
00097                                   EVENT_CALLBACK aHandleEventFunction,
00098                                   nsIDeviceContext *aContext,
00099                                   nsIAppShell *aAppShell,
00100                                   nsWidgetInitData *aInitData, HWND hwndO)
00101 {
00102    nsRect rect = aRect;
00103    if( aParent)  // Offset rect by position of owner
00104    {
00105       nsRect clientRect;
00106       aParent->GetBounds(rect);
00107       aParent->GetClientBounds(clientRect);
00108       rect.x += aRect.x + clientRect.x;
00109       rect.y += aRect.y + clientRect.y;
00110       rect.width = aRect.width;
00111       rect.height = aRect.height;
00112       hwndP = aParent->GetMainWindow();
00113       rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (rect.y + rect.height);
00114    }
00115    else          // Use original rect, no owner window
00116    {
00117       rect = aRect;
00118       rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (aRect.y + aRect.height);
00119    }
00120 
00121 #if DEBUG_sobotka
00122    printf("\nIn nsFrameWindow::RealDoCreate:\n");
00123    printf("   hwndP = %lu\n", hwndP);
00124    printf("   aParent = 0x%lx\n", &aParent);
00125    printf("   aRect = %ld, %ld, %ld, %ld\n", aRect.x, aRect.y, aRect.height, aRect.width);
00126 #endif
00127 
00128    ULONG fcfFlags = GetFCFlags();
00129 
00130    ULONG style = WindowStyle();
00131    if( aInitData)
00132    {
00133       if( aInitData->clipChildren)
00134          style |= WS_CLIPCHILDREN;
00135 #if 0
00136       //
00137       // Windows has a slightly different idea of what the implications are
00138       // of a window having or not having the CLIPSIBLINGS style.
00139       // All 'canvas' components we create must have clipsiblings, or
00140       // strange things happen & performance actually degrades.
00141       //
00142       else
00143         style &= ~WS_CLIPCHILDREN;
00144 #endif
00145 
00146       if( aInitData->clipSiblings)
00147          style |= WS_CLIPSIBLINGS;
00148       else
00149          style &= ~WS_CLIPSIBLINGS;
00150    }
00151 
00152 #ifdef DEBUG_FOCUS
00153    mWindowIdentifier = currentWindowIdentifier;
00154    currentWindowIdentifier++;
00155    if (aInitData && (aInitData->mWindowType == eWindowType_toplevel))
00156      DEBUGFOCUS(Create Frame Window);
00157    else
00158      DEBUGFOCUS(Create Window);
00159 #endif
00160 
00161    mFrameWnd = WinCreateStdWindow( HWND_DESKTOP,
00162                                    0,
00163                                    &fcfFlags,
00164                                    WindowClass(),
00165                                    "Title",
00166                                    style,
00167                                    NULLHANDLE,
00168                                    0,
00169                                    &mWnd);
00170 
00171   
00172    /* Because WinCreateStdWindow doesn't take an owner, we have to set it */
00173    if (hwndP)
00174      WinSetOwner(mFrameWnd, hwndP);
00175 
00176 
00177    /* Set some HWNDs and style into properties for fullscreen mode */
00178    HWND hwndTitleBar = WinWindowFromID(mFrameWnd, FID_TITLEBAR);
00179    WinSetProperty(mFrameWnd, "hwndTitleBar", (PVOID)hwndTitleBar, 0);
00180    HWND hwndSysMenu = WinWindowFromID(mFrameWnd, FID_SYSMENU);
00181    WinSetProperty(mFrameWnd, "hwndSysMenu", (PVOID)hwndSysMenu, 0);
00182    HWND hwndMinMax = WinWindowFromID(mFrameWnd, FID_MINMAX);
00183    WinSetProperty(mFrameWnd, "hwndMinMax", (PVOID)hwndMinMax, 0);
00184 
00185 
00186    SetWindowListVisibility( PR_FALSE);  // Hide from Window List until shown
00187 
00188    NS_ASSERTION( mFrameWnd, "Couldn't create frame");
00189 
00190    // Frames have a minimum height based on the pieces they are created with,
00191    // such as titlebar, menubar, frame borders, etc.  We need this minimum
00192    // height so we can correctly set the frame position (coordinate flipping).
00193    nsRect frameRect = rect;
00194    long minheight; 
00195 
00196    if ( fcfFlags & FCF_SIZEBORDER) {
00197       minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER);
00198    }
00199    else if ( fcfFlags & FCF_DLGBORDER) {
00200       minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME);
00201    }
00202    else {
00203       minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER);
00204    }
00205    if ( fcfFlags & FCF_TITLEBAR) {
00206       minheight += WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR);
00207    }
00208    if ( frameRect.height < minheight) {
00209       frameRect.height = minheight;
00210    }
00211 
00212    // Set up parent data - don't addref to avoid circularity
00213    mParent = nsnull;
00214 
00215    // Make sure we have a device context from somewhere
00216    if( aContext)
00217    {
00218       mContext = aContext;
00219       NS_ADDREF(mContext);
00220    }
00221    else
00222    {
00223       nsresult rc;
00224       static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
00225 
00226       rc = CallCreateInstance(kDeviceContextCID, &mContext);
00227       if( NS_SUCCEEDED(rc))
00228          mContext->Init( (nsNativeWidget) mWnd);
00229 #ifdef DEBUG
00230       else
00231          printf( "Couldn't find DC instance for nsWindow\n");
00232 #endif
00233    }
00234 
00235    // Record bounds.  This is XP, the rect of the entire main window in
00236    // parent space.  Returned by GetBounds().
00237    // NB: We haven't subclassed yet, so callbacks to change mBounds won't
00238    //     have happened!
00239    mBounds = frameRect;
00240    mBounds.height = frameRect.height;
00241 
00242    // Record passed in things
00243    mAppShell = aAppShell;
00244 
00245 //   NS_IF_ADDREF( mAppShell);
00246    GetAppShell();  // Let the base widget class update the refcount for us....
00247    mEventCallback = aHandleEventFunction;
00248 
00249    if( mParent)
00250       mParent->AddChild( this);
00251 
00252    // call the event callback to notify about creation
00253 
00254    DispatchStandardEvent( NS_CREATE );
00255    SubclassWindow(TRUE);
00256    PostCreateWidget();
00257 
00258    // Subclass frame
00259    fnwpDefFrame = WinSubclassWindow( mFrameWnd, fnwpFrame);
00260    WinSetWindowPtr( mFrameWnd, QWL_USER, this);
00261 
00262 
00263    WinSetWindowPos(mFrameWnd, 0, frameRect.x, frameRect.y, frameRect.width, frameRect.height, SWP_SIZE | SWP_MOVE);
00264 }
00265 
00266 
00267 void nsFrameWindow::UpdateClientSize()
00268 {
00269    RECTL rcl = { 0, 0, mBounds.width, mBounds.height };
00270    WinCalcFrameRect( mFrameWnd, &rcl, TRUE); // provided == frame rect
00271    mSizeClient.width = rcl.xRight - rcl.xLeft;
00272    mSizeClient.height = rcl.yTop - rcl.yBottom;
00273    mSizeBorder.width = (mBounds.width - mSizeClient.width) / 2;
00274    mSizeBorder.height = (mBounds.height - mSizeClient.height) / 2;
00275 }
00276 
00277 nsresult nsFrameWindow::GetClientBounds( nsRect &aRect)
00278 {
00279    RECTL rcl = { 0, 0, mBounds.width, mBounds.height };
00280    WinCalcFrameRect( mFrameWnd, &rcl, TRUE); // provided == frame rect
00281    aRect.x = rcl.xLeft;
00282    aRect.y = mBounds.height - rcl.yTop;
00283    aRect.width = mSizeClient.width;
00284    aRect.height = mSizeClient.height;
00285    return NS_OK;
00286 }
00287 
00288 // Just ignore this callback; the correct stuff is done in the frame wp.
00289 PRBool nsFrameWindow::OnReposition( PSWP pSwp)
00290 {
00291    return PR_TRUE;
00292 }
00293 
00294 // For frame windows, 'Show' is equivalent to 'Show & Activate'
00295 nsresult nsFrameWindow::Show( PRBool bState)
00296 {
00297    if( mWnd)
00298    {
00299       ULONG ulFlags;
00300       if( bState) {
00301          ULONG ulStyle = WinQueryWindowULong( GetMainWindow(), QWL_STYLE);
00302          ulFlags = SWP_SHOW;
00303          /* Don't activate the window unless the parent is visible */
00304          if (WinIsWindowVisible(WinQueryWindow(GetMainWindow(), QW_PARENT)))
00305            ulFlags |= SWP_ACTIVATE;
00306          if (!( ulStyle & WS_VISIBLE)) {
00307             PRInt32 sizeMode;
00308             GetSizeMode( &sizeMode);
00309             if ( sizeMode == nsSizeMode_Maximized) {
00310                ulFlags |= SWP_MAXIMIZE;
00311             } else if ( sizeMode == nsSizeMode_Minimized) {
00312                ulFlags |= SWP_MINIMIZE;
00313             } else {
00314                ulFlags |= SWP_RESTORE;
00315             }
00316          }
00317          if( ulStyle & WS_MINIMIZED)
00318             ulFlags |= (SWP_RESTORE | SWP_MAXIMIZE);
00319       }
00320       else
00321          ulFlags = SWP_HIDE | SWP_DEACTIVATE;
00322       WinSetWindowPos( GetMainWindow(), NULLHANDLE, 0L, 0L, 0L, 0L, ulFlags);
00323       SetWindowListVisibility( bState);
00324    }
00325 
00326    return NS_OK;
00327 }
00328 
00329 // Subclass for frame window
00330 MRESULT EXPENTRY fnwpFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
00331 {
00332    // check to see if we have a rollup listener registered
00333    if (nsnull != gRollupListener && nsnull != gRollupWidget) {
00334       if (msg == WM_TRACKFRAME || msg == WM_MINMAXFRAME ||
00335           msg == WM_BUTTON1DOWN || msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN) {
00336          // Rollup if the event is outside the popup
00337          if (PR_FALSE == nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) {
00338             gRollupListener->Rollup();
00339 
00340             // if we are supposed to be consuming events and it is
00341             // a Mouse Button down, let it go through
00342 //            if (gRollupConsumeRollupEvent && msg != WM_BUTTON1DOWN) {
00343 //               return FALSE;
00344 //            }
00345          } 
00346       }
00347    }
00348 
00349    nsFrameWindow *pFrame = (nsFrameWindow*) WinQueryWindowPtr( hwnd, QWL_USER);
00350    return pFrame->FrameMessage( msg, mp1, mp2);
00351 }
00352 
00353 // Process messages from the frame
00354 MRESULT nsFrameWindow::FrameMessage( ULONG msg, MPARAM mp1, MPARAM mp2)
00355 {
00356    MRESULT mresult = 0;
00357    BOOL    bDone = FALSE;
00358 
00359    switch (msg)
00360    {
00361       case WM_WINDOWPOSCHANGED:
00362       {
00363          PSWP pSwp = (PSWP) mp1;
00364 
00365          // Note that client windows never get 'move' messages (well, they won't here anyway)
00366          if( pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE))
00367          {
00368             // These commented-out `-1's cancel each other out.
00369             POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy /* - 1 */ };
00370             ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y /* - 1*/ ;
00371             mBounds.x = ptl.x;
00372             mBounds.y = ptl.y;
00373             OnMove( ptl.x, ptl.y);
00374          }
00375 
00376          // When the frame is sized, do stuff to recalculate client size.
00377          if( pSwp->fl & SWP_SIZE && !(pSwp->fl & SWP_MINIMIZE))
00378          {
00379             mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
00380             bDone = TRUE;
00381 
00382             mBounds.width = pSwp->cx;
00383             mBounds.height = pSwp->cy;
00384 
00385             UpdateClientSize();
00386             DispatchResizeEvent( mSizeClient.width, mSizeClient.height);
00387          }
00388  
00389          if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) {
00390            nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
00391             if (pSwp->fl & SWP_MAXIMIZE)
00392               event.mSizeMode = nsSizeMode_Maximized;
00393             else if (pSwp->fl & SWP_MINIMIZE)
00394               event.mSizeMode = nsSizeMode_Minimized;
00395             else
00396               event.mSizeMode = nsSizeMode_Normal;
00397             InitEvent(event);
00398             DispatchWindowEvent(&event);
00399             NS_RELEASE(event.widget);
00400          }
00401 
00402          break;
00403       }
00404 
00405       // a frame window in kiosk/fullscreen mode must have its frame
00406       // controls reattached before it's minimized & detached after it's
00407       // restored;  if this doesn't happen at the correct times, clicking
00408       // on the icon won't restore it, the sysmenu will have the wrong
00409       // items, and/or the minmax button will have the wrong buttons
00410 
00411       case WM_ADJUSTWINDOWPOS:
00412       {
00413         if (mChromeHidden && ((PSWP)mp1)->fl & SWP_MINIMIZE) {
00414           HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax");
00415           if (hwndTemp)
00416             WinSetParent(hwndTemp, mFrameWnd, TRUE);
00417           hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
00418           if (hwndTemp)
00419             WinSetParent(hwndTemp, mFrameWnd, TRUE);
00420           hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
00421           if (hwndTemp)
00422             WinSetParent(hwndTemp, mFrameWnd, TRUE);
00423         }
00424         break;
00425       }
00426       case WM_ADJUSTFRAMEPOS:
00427       {
00428         if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) {
00429           HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
00430           if (hwndTemp)
00431             WinSetParent(hwndTemp, HWND_OBJECT, TRUE);
00432           hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
00433           if (hwndTemp)
00434             WinSetParent(hwndTemp, HWND_OBJECT, TRUE);
00435           hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax");
00436           if (hwndTemp)
00437             WinSetParent(hwndTemp, HWND_OBJECT, TRUE);
00438         }
00439         break;
00440       }
00441 
00442       case WM_DESTROY:
00443          DEBUGFOCUS(frame WM_DESTROY);
00444          WinSubclassWindow( mFrameWnd, fnwpDefFrame);
00445          WinSetWindowPtr( mFrameWnd, QWL_USER, 0);
00446          WinRemoveProperty(mFrameWnd, "hwndTitleBar");
00447          WinRemoveProperty(mFrameWnd, "hwndSysMenu");
00448          WinRemoveProperty(mFrameWnd, "hwndMinMax");
00449          WinRemoveProperty(mFrameWnd, "ulStyle");
00450          break;
00451       case WM_INITMENU:
00452          /* If we are in fullscreen/kiosk mode, disable maximize menu item */
00453          if (mChromeHidden) {
00454             if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
00455               if (SHORT1FROMMP(mp1) == SC_SYSMENU) {
00456                 MENUITEM menuitem;
00457                 WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM, MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem));
00458                 mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
00459                 WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE);
00460                 bDone = TRUE;
00461               }
00462             }
00463          }
00464          break;
00465       case WM_SYSCOMMAND:
00466          /* If we are in fullscreen/kiosk mode, don't honor maximize requests */
00467          if (mChromeHidden) {
00468             if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
00469               if ((SHORT1FROMMP(mp1) == SC_MAXIMIZE))
00470               {
00471                 bDone = TRUE;
00472               }
00473             }
00474          }
00475          break;
00476 
00477       case WM_ACTIVATE:
00478         DEBUGFOCUS(frame WM_ACTIVATE);
00479         if (SHORT1FROMMP(mp1) &&
00480             !(WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED)) {
00481            bDone = DispatchFocus(NS_GOTFOCUS, PR_TRUE);
00482         }
00483         break;
00484    }
00485 
00486    if( !bDone)
00487       mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
00488 
00489    return mresult;
00490 }