Files
Mozilla/mozilla/widget/src/os2/nsFrameWindow.cpp
jst%mozilla.jstenback.com ebed1ee784 Fixing bug 289940. Make chrome event handlers only receive trusted events by default. r=jonas@sicking.cc, sr=peterv@propagandism.org, a=chofmann@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@172848 18797224-902f-48f8-a5cc-f745e15eee43
2005-04-28 23:48:28 +00:00

465 lines
16 KiB
C++

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla OS/2 libraries.
*
* The Initial Developer of the Original Code is
* John Fairhurst, <john_fairhurst@iname.com>.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
*
* This Original Code has been modified by IBM Corporation.
* Modifications made by IBM described herein are
* Copyright (c) International Business Machines
* Corporation, 2000
*
* Modifications to Mozilla code or documentation
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 03/23/2000 IBM Corp. Fix missing title bars on profile wizard windows.
* 04/11/2000 IBM Corp. Remove assertion.
* 05/10/2000 IBM Corp. Correct initial position of frame w/titlebar
* 06/21/2000 IBM Corp. Use rollup listener from nsWindow
*/
// Frame window - produced when NS_WINDOW_CID is required.
#include "nsFrameWindow.h"
#include "nsIRollupListener.h"
#include "nsIDeviceContext.h"
#include "nsIComponentManager.h"
#include "nsGfxCIID.h"
extern nsIRollupListener * gRollupListener;
extern nsIWidget * gRollupWidget;
extern PRBool gRollupConsumeRollupEvent;
nsFrameWindow::nsFrameWindow() : nsWindow()
{
fnwpDefFrame = 0;
mWindowType = eWindowType_toplevel;
}
nsFrameWindow::~nsFrameWindow()
{
}
void nsFrameWindow::SetWindowListVisibility( PRBool bState)
{
HSWITCH hswitch;
SWCNTRL swctl;
hswitch = WinQuerySwitchHandle(mFrameWnd, 0);
if( hswitch)
{
WinQuerySwitchEntry( hswitch, &swctl);
swctl.uchVisibility = bState ? SWL_VISIBLE : SWL_INVISIBLE;
swctl.fbJump = bState ? SWL_JUMPABLE : SWL_NOTJUMPABLE;
WinChangeSwitchEntry( hswitch, &swctl);
}
}
// Called in the PM thread.
void nsFrameWindow::RealDoCreate( HWND hwndP, nsWindow *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsWidgetInitData *aInitData, HWND hwndO)
{
nsRect rect = aRect;
if( aParent) // Offset rect by position of owner
{
nsRect clientRect;
aParent->GetBounds(rect);
aParent->GetClientBounds(clientRect);
rect.x += aRect.x + clientRect.x;
rect.y += aRect.y + clientRect.y;
rect.width = aRect.width;
rect.height = aRect.height;
hwndP = aParent->GetMainWindow();
rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (rect.y + rect.height);
}
else // Use original rect, no owner window
{
rect = aRect;
rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (aRect.y + aRect.height);
}
#if DEBUG_sobotka
printf("\nIn nsFrameWindow::RealDoCreate:\n");
printf(" hwndP = %lu\n", hwndP);
printf(" aParent = 0x%lx\n", &aParent);
printf(" aRect = %ld, %ld, %ld, %ld\n", aRect.x, aRect.y, aRect.height, aRect.width);
#endif
ULONG fcfFlags = GetFCFlags();
ULONG style = WindowStyle();
if( aInitData)
{
if( aInitData->clipChildren)
style |= WS_CLIPCHILDREN;
#if 0
//
// Windows has a slightly different idea of what the implications are
// of a window having or not having the CLIPSIBLINGS style.
// All 'canvas' components we create must have clipsiblings, or
// strange things happen & performance actually degrades.
//
else
style &= ~WS_CLIPCHILDREN;
#endif
if( aInitData->clipSiblings)
style |= WS_CLIPSIBLINGS;
else
style &= ~WS_CLIPSIBLINGS;
}
mFrameWnd = WinCreateStdWindow( HWND_DESKTOP,
0,
&fcfFlags,
WindowClass(),
"Title",
style,
NULLHANDLE,
0,
&mWnd);
/* Because WinCreateStdWindow doesn't take an owner, we have to set it */
if (hwndP)
WinSetOwner(mFrameWnd, hwndP);
/* Set some HWNDs and style into properties for fullscreen mode */
HWND hwndTitleBar = WinWindowFromID(mFrameWnd, FID_TITLEBAR);
WinSetProperty(mFrameWnd, "hwndTitleBar", (PVOID)hwndTitleBar, 0);
HWND hwndSysMenu = WinWindowFromID(mFrameWnd, FID_SYSMENU);
WinSetProperty(mFrameWnd, "hwndSysMenu", (PVOID)hwndSysMenu, 0);
HWND hwndMinMax = WinWindowFromID(mFrameWnd, FID_MINMAX);
WinSetProperty(mFrameWnd, "hwndMinMax", (PVOID)hwndMinMax, 0);
SetWindowListVisibility( PR_FALSE); // Hide from Window List until shown
NS_ASSERTION( mFrameWnd, "Couldn't create frame");
// Frames have a minimum height based on the pieces they are created with,
// such as titlebar, menubar, frame borders, etc. We need this minimum
// height so we can correctly set the frame position (coordinate flipping).
nsRect frameRect = rect;
long minheight;
if ( fcfFlags & FCF_SIZEBORDER) {
minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER);
}
else if ( fcfFlags & FCF_DLGBORDER) {
minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME);
}
else {
minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER);
}
if ( fcfFlags & FCF_TITLEBAR) {
minheight += WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR);
}
if ( frameRect.height < minheight) {
frameRect.height = minheight;
}
// Set up parent data - don't addref to avoid circularity
mParent = nsnull;
// Make sure we have a device context from somewhere
if( aContext)
{
mContext = aContext;
NS_ADDREF(mContext);
}
else
{
nsresult rc;
static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
rc = CallCreateInstance(kDeviceContextCID, &mContext);
if( NS_SUCCEEDED(rc))
mContext->Init( (nsNativeWidget) mWnd);
#ifdef DEBUG
else
printf( "Couldn't find DC instance for nsWindow\n");
#endif
}
// Record bounds. This is XP, the rect of the entire main window in
// parent space. Returned by GetBounds().
// NB: We haven't subclassed yet, so callbacks to change mBounds won't
// have happened!
mBounds = frameRect;
mBounds.height = frameRect.height;
// Record passed in things
mAppShell = aAppShell;
// NS_IF_ADDREF( mAppShell);
GetAppShell(); // Let the base widget class update the refcount for us....
mEventCallback = aHandleEventFunction;
if( mParent)
mParent->AddChild( this);
// call the event callback to notify about creation
DispatchStandardEvent( NS_CREATE );
SubclassWindow(TRUE);
PostCreateWidget();
// Subclass frame
fnwpDefFrame = WinSubclassWindow( mFrameWnd, fnwpFrame);
WinSetWindowPtr( mFrameWnd, QWL_USER, this);
WinSetWindowPos(mFrameWnd, 0, frameRect.x, frameRect.y, frameRect.width, frameRect.height, SWP_SIZE | SWP_MOVE);
}
void nsFrameWindow::UpdateClientSize()
{
RECTL rcl = { 0, 0, mBounds.width, mBounds.height };
WinCalcFrameRect( mFrameWnd, &rcl, TRUE); // provided == frame rect
mSizeClient.width = rcl.xRight - rcl.xLeft;
mSizeClient.height = rcl.yTop - rcl.yBottom;
mSizeBorder.width = (mBounds.width - mSizeClient.width) / 2;
mSizeBorder.height = (mBounds.height - mSizeClient.height) / 2;
}
nsresult nsFrameWindow::GetClientBounds( nsRect &aRect)
{
RECTL rcl = { 0, 0, mBounds.width, mBounds.height };
WinCalcFrameRect( mFrameWnd, &rcl, TRUE); // provided == frame rect
aRect.x = rcl.xLeft;
aRect.y = mBounds.height - rcl.yTop;
aRect.width = mSizeClient.width;
aRect.height = mSizeClient.height;
return NS_OK;
}
// Just ignore this callback; the correct stuff is done in the frame wp.
PRBool nsFrameWindow::OnReposition( PSWP pSwp)
{
return PR_TRUE;
}
// For frame windows, 'Show' is equivalent to 'Show & Activate'
nsresult nsFrameWindow::Show( PRBool bState)
{
if( mWnd)
{
ULONG ulFlags;
if( bState) {
ULONG ulStyle = WinQueryWindowULong( GetMainWindow(), QWL_STYLE);
ulFlags = SWP_SHOW;
/* Don't activate the window unless the parent is visible */
if (WinIsWindowVisible(WinQueryWindow(GetMainWindow(), QW_PARENT)))
ulFlags |= SWP_ACTIVATE;
if (!( ulStyle & WS_VISIBLE)) {
PRInt32 sizeMode;
GetSizeMode( &sizeMode);
if ( sizeMode == nsSizeMode_Maximized) {
ulFlags |= SWP_MAXIMIZE;
} else if ( sizeMode == nsSizeMode_Minimized) {
ulFlags |= SWP_MINIMIZE;
} else {
ulFlags |= SWP_RESTORE;
}
}
if( ulStyle & WS_MINIMIZED)
ulFlags |= (SWP_RESTORE | SWP_MAXIMIZE);
}
else
ulFlags = SWP_HIDE | SWP_DEACTIVATE;
WinSetWindowPos( GetMainWindow(), NULLHANDLE, 0L, 0L, 0L, 0L, ulFlags);
SetWindowListVisibility( bState);
}
return NS_OK;
}
// Subclass for frame window
MRESULT EXPENTRY fnwpFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
// check to see if we have a rollup listener registered
if (nsnull != gRollupListener && nsnull != gRollupWidget) {
if (msg == WM_TRACKFRAME || msg == WM_MINMAXFRAME ||
msg == WM_BUTTON1DOWN || msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN) {
// Rollup if the event is outside the popup
if (PR_FALSE == nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) {
gRollupListener->Rollup();
// if we are supposed to be consuming events and it is
// a Mouse Button down, let it go through
// if (gRollupConsumeRollupEvent && msg != WM_BUTTON1DOWN) {
// return FALSE;
// }
}
}
}
nsFrameWindow *pFrame = (nsFrameWindow*) WinQueryWindowPtr( hwnd, QWL_USER);
return pFrame->FrameMessage( msg, mp1, mp2);
}
// Process messages from the frame
MRESULT nsFrameWindow::FrameMessage( ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mresult = 0;
BOOL bDone = FALSE;
switch (msg)
{
case WM_WINDOWPOSCHANGED:
{
PSWP pSwp = (PSWP) mp1;
// Note that client windows never get 'move' messages (well, they won't here anyway)
if( pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE))
{
// These commented-out `-1's cancel each other out.
POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy /* - 1 */ };
ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y /* - 1*/ ;
mBounds.x = ptl.x;
mBounds.y = ptl.y;
OnMove( ptl.x, ptl.y);
}
// When the frame is sized, do stuff to recalculate client size.
if( pSwp->fl & SWP_SIZE && !(pSwp->fl & SWP_MINIMIZE))
{
mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
bDone = TRUE;
mBounds.width = pSwp->cx;
mBounds.height = pSwp->cy;
UpdateClientSize();
DispatchResizeEvent( mSizeClient.width, mSizeClient.height);
}
if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) {
nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
if (pSwp->fl & SWP_MAXIMIZE)
event.mSizeMode = nsSizeMode_Maximized;
else if (pSwp->fl & SWP_MINIMIZE)
event.mSizeMode = nsSizeMode_Minimized;
else
event.mSizeMode = nsSizeMode_Normal;
InitEvent(event);
DispatchWindowEvent(&event);
NS_RELEASE(event.widget);
}
break;
}
case WM_ADJUSTWINDOWPOS:
{
PSWP pswp = (PSWP)mp1;
#if 0
if (pswp->fl & SWP_ZORDER)
ConstrainZLevel(&pswp->hwndInsertBehind);
#endif
if (mChromeHidden) {
if (pswp->fl & SWP_MINIMIZE) {
HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
if (hwndTemp)
WinSetParent(hwndTemp, mFrameWnd, TRUE);
}
if (pswp->fl & SWP_RESTORE) {
HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
if (hwndTemp)
WinSetParent(hwndTemp, HWND_OBJECT, TRUE);
}
}
}
break;
case WM_DESTROY:
WinSubclassWindow( mFrameWnd, fnwpDefFrame);
WinSetWindowPtr( mFrameWnd, QWL_USER, 0);
WinRemoveProperty(mFrameWnd, "hwndTitleBar");
WinRemoveProperty(mFrameWnd, "hwndSysMenu");
WinRemoveProperty(mFrameWnd, "hwndMinMax");
WinRemoveProperty(mFrameWnd, "ulStyle");
break;
case WM_INITMENU:
/* If we are in fullscreen/kiosk mode, disable maximize menu item */
if (mChromeHidden) {
if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
if (SHORT1FROMMP(mp1) == SC_SYSMENU) {
MENUITEM menuitem;
WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM, MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem));
mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE);
bDone = TRUE;
}
}
}
break;
case WM_SYSCOMMAND:
/* If we are in fullscreen/kiosk mode, don't honor maximize requests */
if (mChromeHidden) {
if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
if ((SHORT1FROMMP(mp1) == SC_MAXIMIZE))
{
bDone = TRUE;
}
}
}
break;
/* To simulate Windows better, we need to send a focus message to the */
/* client when the frame is activated if there is a non mozilla window focused */
case WM_ACTIVATE:
#ifdef DEBUG_FOCUS
printf("[%x] WM_ACTIVATE (%d)\n", this, mWindowIdentifier);
#endif
if (SHORT1FROMMP(mp1)) {
#ifdef DEBUG_FOCUS
printf("[%x] NS_GOTFOCUS (%d)\n", this, mWindowIdentifier);
#endif
bDone = DispatchFocus(NS_GOTFOCUS, PR_TRUE);
}
break;
}
if( !bDone)
mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2);
return mresult;
}