Bug 533200: [OS/2] Replace nsFrameWindow with os2FrameWindow r=wuno

This commit is contained in:
Rich Walsh 2010-03-06 12:52:10 -05:00
Родитель 454cbf1f10
Коммит 9495bc48b9
8 изменённых файлов: 1023 добавлений и 944 удалений

Просмотреть файл

@ -61,7 +61,7 @@ CPPSRCS = \
nsBidiKeyboard.cpp \
nsClipboard.cpp \
nsFilePicker.cpp \
nsFrameWindow.cpp \
os2FrameWindow.cpp \
nsLookAndFeel.cpp \
nsOS2Uni.cpp \
nsPrintOS2.cpp \

Просмотреть файл

@ -1,505 +0,0 @@
/* vim: set sw=2 sts=2 et cin: */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** 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):
* Rich Walsh <dragtext@e-vertise.com>
*
* 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 are
* Copyright (c) International Business Machines Corporation, 2000
*
*/
//=============================================================================
#include "nsFrameWindow.h"
#include "nsIRollupListener.h"
//-----------------------------------------------------------------------------
extern nsIRollupListener* gRollupListener;
extern nsIWidget* gRollupWidget;
extern PRBool gRollupConsumeRollupEvent;
extern PRUint32 gOS2Flags;
#ifdef DEBUG_FOCUS
extern int currentWindowIdentifier;
#endif
//=============================================================================
// nsFrameWindow Setup
//=============================================================================
nsFrameWindow::nsFrameWindow() : nsWindow()
{
mPrevFrameProc = 0;
mWindowType = eWindowType_toplevel;
mNeedActivation = PR_FALSE;
}
nsFrameWindow::~nsFrameWindow()
{
}
//-----------------------------------------------------------------------------
// Create frame & client windows for an nsFrameWindow object
nsresult nsFrameWindow::CreateWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
PRUint32 aStyle)
{
// top-level widget windows (i.e nsFrameWindow) are created for
// windows of types eWindowType_toplevel, *_dialog, & *_invisible
mIsTopWidgetWindow = PR_TRUE;
// Create a frame window with a MozillaWindowClass window as its client.
PRUint32 fcfFlags = GetFCFlags();
mFrameWnd = WinCreateStdWindow(HWND_DESKTOP,
0,
(ULONG*)&fcfFlags,
kWindowClassName,
"Title",
aStyle,
NULLHANDLE,
0,
&mWnd);
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_FAILURE);
// Hide from the Window List until shown.
SetWindowListVisibility(PR_FALSE);
// This prevents a modal dialog from being covered by its disabled parent.
if (aParentWnd != HWND_DESKTOP) {
WinSetOwner(mFrameWnd, aParentWnd);
}
// Set the frame control HWNDs as properties for use by fullscreen mode.
HWND hTemp = WinWindowFromID(mFrameWnd, FID_TITLEBAR);
WinSetProperty(mFrameWnd, "hwndTitleBar", (PVOID)hTemp, 0);
hTemp = WinWindowFromID(mFrameWnd, FID_SYSMENU);
WinSetProperty(mFrameWnd, "hwndSysMenu", (PVOID)hTemp, 0);
hTemp = WinWindowFromID(mFrameWnd, FID_MINMAX);
WinSetProperty(mFrameWnd, "hwndMinMax", (PVOID)hTemp, 0);
// Establish a minimum height or else some dialogs will be truncated.
PRInt32 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);
}
// Store the frame's adjusted dimensions, move & resize accordingly,
// then calculate the client's dimensions.
mBounds = aRect;
if (mBounds.height < minHeight) {
mBounds.height = minHeight;
}
PRInt32 pmY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
- mBounds.y - mBounds.height;
WinSetWindowPos(mFrameWnd, 0, mBounds.x, pmY,
mBounds.width, mBounds.height, SWP_SIZE | SWP_MOVE);
UpdateClientSize();
// Subclass the frame; the client will be subclassed by Create().
mPrevFrameProc = WinSubclassWindow(mFrameWnd, fnwpFrame);
WinSetWindowPtr(mFrameWnd, QWL_USER, this);
DEBUGFOCUS(Create nsFrameWindow);
return NS_OK;
}
//-----------------------------------------------------------------------------
PRUint32 nsFrameWindow::GetFCFlags()
{
PRUint32 style = FCF_TITLEBAR | FCF_SYSMENU | FCF_TASKLIST |
FCF_CLOSEBUTTON | FCF_NOBYTEALIGN | FCF_AUTOICON;
if (mWindowType == eWindowType_dialog) {
if (mBorderStyle == eBorderStyle_default) {
style |= FCF_DLGBORDER;
} else {
style |= FCF_SIZEBORDER | FCF_MINMAX;
}
}
else {
style |= FCF_SIZEBORDER | FCF_MINMAX;
}
if (gOS2Flags & kIsDBCS) {
style |= FCF_DBE_APPSTAT;
}
if (mWindowType == eWindowType_invisible) {
style &= ~FCF_TASKLIST;
}
if (mBorderStyle != eBorderStyle_default &&
mBorderStyle != eBorderStyle_all) {
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_resizeh)) {
style &= ~FCF_SIZEBORDER;
style |= FCF_DLGBORDER;
}
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_border)) {
style &= ~(FCF_DLGBORDER | FCF_SIZEBORDER);
}
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_title)) {
style &= ~(FCF_TITLEBAR | FCF_TASKLIST);
}
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_close)) {
style &= ~FCF_CLOSEBUTTON;
}
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & (eBorderStyle_menu | eBorderStyle_close))) {
style &= ~FCF_SYSMENU;
}
// Looks like getting rid of the system menu also does away
// with the close box. So, we only get rid of the system menu
// if you want neither it nor the close box.
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_minimize)) {
style &= ~FCF_MINBUTTON;
}
if (mBorderStyle == eBorderStyle_none ||
!(mBorderStyle & eBorderStyle_maximize)) {
style &= ~FCF_MAXBUTTON;
}
}
return style;
}
//=============================================================================
// Window Operations
//=============================================================================
// For frame windows, 'Show' is equivalent to 'Show & Activate'
NS_METHOD nsFrameWindow::Show(PRBool aState)
{
if (!mWnd) {
return NS_OK;
}
PRUint32 ulFlags;
if (!aState) {
ulFlags = SWP_HIDE | SWP_DEACTIVATE;
} else {
ulFlags = SWP_SHOW;
// Don't activate the window unless the parent is visible
if (WinIsWindowVisible(WinQueryWindow(mFrameWnd, QW_PARENT))) {
ulFlags |= SWP_ACTIVATE;
}
PRUint32 ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
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);
}
}
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, ulFlags);
SetWindowListVisibility(aState);
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsFrameWindow::GetClientBounds(nsIntRect& 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;
}
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
// When WM_ACTIVATE is received with the "gaining activation" flag set,
// the frame's wndproc sets mNeedActivation. Later, when an nsWindow
// gets a WM_FOCUSCHANGED msg with the "gaining focus" flag set, it
// invokes this method on nsFrameWindow to fire an NS_ACTIVATE event.
void nsFrameWindow::ActivateTopLevelWidget()
{
// Don't fire event if we're minimized or else the window will
// be restored as soon as the user clicks on it. When the user
// explicitly restores it, SetSizeMode() will call this method.
if (mNeedActivation) {
PRInt32 sizeMode;
GetSizeMode(&sizeMode);
if (sizeMode != nsSizeMode_Minimized) {
mNeedActivation = PR_FALSE;
DEBUGFOCUS(NS_ACTIVATE);
DispatchActivationEvent(NS_ACTIVATE);
}
}
return;
}
//-----------------------------------------------------------------------------
// Just ignore this callback; the correct stuff is done in the frame wp.
PRBool nsFrameWindow::OnReposition(PSWP pSwp)
{
return PR_TRUE;
}
//-----------------------------------------------------------------------------
void nsFrameWindow::SetWindowListVisibility(PRBool aState)
{
HSWITCH hswitch = WinQuerySwitchHandle(mFrameWnd, 0);
if (hswitch) {
SWCNTRL swctl;
WinQuerySwitchEntry(hswitch, &swctl);
swctl.uchVisibility = aState ? SWL_VISIBLE : SWL_INVISIBLE;
swctl.fbJump = aState ? SWL_JUMPABLE : SWL_NOTJUMPABLE;
WinChangeSwitchEntry(hswitch, &swctl);
}
}
//=============================================================================
// nsFrameWindow's Window Procedure
//=============================================================================
// 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 (gRollupListener && 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 (!nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) {
gRollupListener->Rollup(PR_UINT32_MAX, nsnull);
}
}
}
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;
PRBool bDone = PR_FALSE;
switch (msg) {
case WM_WINDOWPOSCHANGED: {
PSWP pSwp = (PSWP)mp1;
// Note that client windows never get 'move' messages
if (pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE)) {
POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy };
ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y;
mBounds.x = ptl.x;
mBounds.y = ptl.y;
DispatchMoveEvent(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 = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
bDone = PR_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);
}
break;
}
// a frame window in kiosk/fullscreen mode must have its frame
// controls reattached before it's minimized & detached after it's
// restored; if this doesn't happen at the correct times, clicking
// on the icon won't restore it, the sysmenu will have the wrong
// items, and/or the minmax button will have the wrong buttons
case WM_ADJUSTWINDOWPOS: {
if (mChromeHidden && ((PSWP)mp1)->fl & SWP_MINIMIZE) {
HWND hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax");
if (hTemp) {
WinSetParent(hTemp, mFrameWnd, TRUE);
}
hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
if (hTemp) {
WinSetParent(hTemp, mFrameWnd, TRUE);
}
hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
if (hTemp) {
WinSetParent(hTemp, mFrameWnd, TRUE);
}
}
break;
}
case WM_ADJUSTFRAMEPOS: {
if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) {
HWND hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
if (hTemp) {
WinSetParent(hTemp, HWND_OBJECT, TRUE);
}
hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
if (hTemp) {
WinSetParent(hTemp, HWND_OBJECT, TRUE);
}
hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax");
if (hTemp) {
WinSetParent(hTemp, HWND_OBJECT, TRUE);
}
}
break;
}
case WM_DESTROY:
DEBUGFOCUS(frame WM_DESTROY);
WinSubclassWindow(mFrameWnd, mPrevFrameProc);
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 &&
SHORT1FROMMP(mp1) == SC_SYSMENU &&
WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
MENUITEM menuitem;
WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM,
MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem));
mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE);
bDone = PR_TRUE;
}
break;
case WM_SYSCOMMAND:
// If we are in fullscreen/kiosk mode, don't honor maximize requests
if (mChromeHidden &&
SHORT1FROMMP(mp1) == SC_MAXIMIZE &&
WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
bDone = PR_TRUE;
}
break;
// When the frame is activated, set a flag to be acted on after
// PM has finished changing focus. When deactivated, dispatch
// the event immediately because it doesn't affect the focus.
case WM_ACTIVATE:
DEBUGFOCUS(WM_ACTIVATE);
if (mp1) {
mNeedActivation = PR_TRUE;
} else {
mNeedActivation = PR_FALSE;
DEBUGFOCUS(NS_DEACTIVATE);
DispatchActivationEvent(NS_DEACTIVATE);
// Prevent the frame from automatically focusing any window
// when it's reactivated. Let moz set the focus to avoid
// having non-widget children of plugins focused in error.
WinSetWindowULong(mFrameWnd, QWL_HWNDFOCUSSAVE, 0);
}
break;
}
if (!bDone) {
mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
}
return mresult;
}
//=============================================================================

Просмотреть файл

@ -1,109 +0,0 @@
/* vim: set sw=2 sts=2 et cin: */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** 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):
* Rich Walsh <dragtext@e-vertise.com>
*
* 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 ***** */
//=============================================================================
/*
* nsFrameWindow is a subclass of nsWindow and is created when NS_WINDOW_CID
* is specified. It represents a top-level widget and is implemented as two
* native windows, a frame (WC_FRAME) and a client (MozillaWindowClass).
*
* Most methods inherited from nsIWidget are handled by nsWindow. For those
* which require slightly different implementations for top-level and child
* widgets, nsWindow relies on a flag or on virtual helper methods to handle
* the differences properly.
*
* There are two items where these differences are particularly important:
* - mWnd identifies the frame's client which is seldom acted upon directly;
* instead, most operations involve mFrameWnd.
* - mBounds contains the dimensions of mFrameWnd, not mWnd whose width and
* height are stored in mSizeClient.
*
*/
//=============================================================================
#ifndef _nsframewindow_h
#define _nsframewindow_h
#include "nsWindow.h"
#include "nssize.h"
//=============================================================================
// nsFrameWindow
//=============================================================================
class nsFrameWindow : public nsWindow
{
public:
nsFrameWindow();
virtual ~nsFrameWindow();
// from nsIWidget
virtual nsresult CreateWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
PRUint32 aStyle);
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD GetClientBounds(nsIntRect& aRect);
protected:
// from nsWindow
virtual HWND GetMainWindow() const {return mFrameWnd;}
virtual void ActivateTopLevelWidget();
virtual PRBool OnReposition(PSWP pSwp);
virtual PRInt32 GetClientHeight() {return mSizeClient.height;}
// nsFrameWindow
PRUint32 GetFCFlags();
void UpdateClientSize();
void SetWindowListVisibility(PRBool aState);
MRESULT FrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2);
friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg,
MPARAM mp1, MPARAM mp2);
PFNWP mPrevFrameProc;
nsSize mSizeClient;
PRBool mNeedActivation;
};
#endif //_nsframewindow_h
//=============================================================================

Просмотреть файл

@ -84,9 +84,6 @@
#include "nsDeviceContextSpecOS2.h"
#include "nsPrintOptionsOS2.h"
#include "nsPrintSession.h"
#include "nsFrameWindow.h" // OS/2 only
#include "nsIdleServiceOS2.h"
// objects that just require generic constructors
@ -95,7 +92,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFrameWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
@ -124,7 +121,7 @@ static const nsModuleComponentInfo components[] =
{ "OS/2 Child Window",
NS_CHILD_CID,
"@mozilla.org/widget/child_window/os2;1",
nsWindowConstructor },
nsChildWindowConstructor },
{ "OS/2 Clipboard",
NS_CLIPBOARD_CID,
"@mozilla.org/widget/clipboard;1",
@ -153,10 +150,10 @@ static const nsModuleComponentInfo components[] =
NS_TOOLKIT_CID,
"@mozilla.org/widget/toolkit/os2;1",
nsToolkitConstructor },
{ "OS/2 Frame Window",
{ "OS/2 Window",
NS_WINDOW_CID,
"@mozilla.org/widget/window/os2;1",
nsFrameWindowConstructor },
nsWindowConstructor },
{ "OS/2 Transferable",
NS_TRANSFERABLE_CID,
"@mozilla.org/widget/transferable;1",

Просмотреть файл

@ -66,6 +66,7 @@
//=============================================================================
#include "nsWindow.h"
#include "os2FrameWindow.h"
#include "gfxContext.h"
#include "gfxOS2Surface.h"
#include "imgIContainer.h"
@ -166,11 +167,21 @@
// name of the window class used to clip plugins
#define kClipWndClass "nsClipWnd"
//-----------------------------------------------------------------------------
// Debug
#ifdef DEBUG_FOCUS
#define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \
(int)this, mWnd, mWindowIdentifier)
#else
#define DEBUGFOCUS(what)
#endif
//=============================================================================
// Variables & Forward declarations
//=============================================================================
// Rollup Listener - used by nsWindow & nsFrameWindow
// Rollup Listener - used by nsWindow & os2FrameWindow
nsIRollupListener* gRollupListener = 0;
nsIMenuRollup* gMenuRollup = 0;
nsIWidget* gRollupWidget = 0;
@ -204,8 +215,8 @@ nsWindow::nsWindow() : nsBaseWidget()
{
mWnd = 0;
mParent = 0;
mIsTopWidgetWindow = PR_FALSE;
mWindowType = eWindowType_child;
mFrame = 0;
mWindowType = eWindowType_toplevel;
mBorderStyle = eBorderStyle_default;
mWindowState = nsWindowState_ePrecreate;
mOnDestroyCalled = PR_FALSE;
@ -217,10 +228,6 @@ nsWindow::nsWindow() : nsBaseWidget()
mCssCursorHPtr = 0;
mThebesSurface = 0;
mFrameWnd = 0;
mFrameIcon = 0;
mChromeHidden = PR_FALSE;
if (!gOS2Flags) {
InitGlobals();
}
@ -239,10 +246,6 @@ nsWindow::~nsWindow()
// may even be illegal to call them from here.
mIsDestroying = PR_TRUE;
if (mFrameIcon) {
WinFreeFileIcon(mFrameIcon);
mFrameIcon = 0;
}
if (mCssCursorHPtr) {
WinDestroyPointer(mCssCursorHPtr);
@ -257,6 +260,12 @@ nsWindow::~nsWindow()
nsWindowState_eInCreate);
Destroy();
}
// If it exists, destroy our os2FrameWindow helper object.
if (mFrame) {
delete mFrame;
mFrame = 0;
}
}
//-----------------------------------------------------------------------------
@ -316,7 +325,7 @@ void nsWindow::ReleaseGlobals()
}
//-----------------------------------------------------------------------------
// Init an nsWindow or nsFrameWindow & create the appropriate native window.
// Init an nsWindow & create the appropriate native window.
NS_METHOD nsWindow::Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
@ -327,12 +336,11 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent,
nsIToolkit* aToolkit,
nsWidgetInitData* aInitData)
{
nsresult rv;
mWindowState = nsWindowState_eInCreate;
// Identify the parent's nsWindow & native window. Only one of these
// should be supplied. Note: only nsWindow saves pParent as mParent;
// nsFrameWindow discards it since toplevel widgets have no parent.
// os2FrameWindow discards it since toplevel widgets have no parent.
HWND hParent;
nsWindow* pParent;
if (aParent) {
@ -357,7 +365,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent,
NS_ADDREF(mContext);
} else {
static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
rv = CallCreateInstance(kDeviceContextCID, &mContext);
nsresult rv = CallCreateInstance(kDeviceContextCID, &mContext);
NS_ENSURE_SUCCESS(rv, rv);
mContext->Init(nsnull);
}
@ -375,30 +383,34 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent,
NS_ADDREF(mToolkit);
}
// Some basic initialization.
PRUint32 style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if (aInitData) {
// While we comply with the clipSiblings flag, we always set
// clipChildren regardless of the flag for performance reasons.
if (!aInitData->clipSiblings) {
style &= ~WS_CLIPSIBLINGS;
}
mWindowType = aInitData->mWindowType;
mBorderStyle = aInitData->mBorderStyle;
}
#ifdef DEBUG_FOCUS
mWindowIdentifier = currentWindowIdentifier;
currentWindowIdentifier++;
#endif
// This is virtual and creates the appropriate type of window for
// the class. It also does a few other class-specific chores.
rv = CreateWindow(pParent, hParent, aRect, style);
NS_ENSURE_SUCCESS(rv, rv);
// Some basic initialization.
if (aInitData) {
mWindowType = aInitData->mWindowType;
mBorderStyle = aInitData->mBorderStyle;
}
// Both versions of CreateWindow() create a MozillaWindow
// class window that needs to store this object's pointer.
// For toplevel windows, create an instance of our helper class,
// then have it create a frame & client window; otherwise,
// call our own CreateWindow() method to create a child window.
if (mWindowType == eWindowType_toplevel ||
mWindowType == eWindowType_dialog ||
mWindowType == eWindowType_invisible) {
mFrame = new os2FrameWindow(this);
NS_ENSURE_TRUE(mFrame, NS_ERROR_FAILURE);
mWnd = mFrame->CreateFrameWindow(pParent, hParent, aRect,
mWindowType, mBorderStyle);
NS_ENSURE_TRUE(mWnd, NS_ERROR_FAILURE);
} else {
nsresult rv = CreateWindow(pParent, hParent, aRect, aInitData);
NS_ENSURE_SUCCESS(rv, rv);
}
// Store a pointer to this object in the window's extra bytes.
SetNSWindowPtr(mWnd, this);
// Finalize the widget creation process.
@ -407,7 +419,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent,
DispatchWindowEvent(&event);
mWindowState = nsWindowState_eLive;
return rv;
return NS_OK;
}
//-----------------------------------------------------------------------------
@ -416,7 +428,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent,
nsresult nsWindow::CreateWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
PRUint32 aStyle)
nsWidgetInitData* aInitData)
{
// For pop-ups, the Desktop is the parent and aParentWnd is the owner.
HWND hOwner = 0;
@ -425,11 +437,18 @@ nsresult nsWindow::CreateWindow(nsWindow* aParent,
aParentWnd = HWND_DESKTOP;
}
// While we comply with the clipSiblings flag, we always set
// clipChildren regardless of the flag for performance reasons.
PRUint32 style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if (aInitData && !aInitData->clipSiblings) {
style &= ~WS_CLIPSIBLINGS;
}
// Create the window hidden; it will be resized below.
mWnd = WinCreateWindow(aParentWnd,
kWindowClassName,
0,
aStyle,
style,
0, 0, 0, 0,
hOwner,
HWND_TOP,
@ -488,9 +507,7 @@ NS_METHOD nsWindow::Destroy()
CaptureRollupEvents(nsnull, nsnull, PR_FALSE, PR_TRUE);
}
// Since this may be called by the destructor, don't use
// GetMainWindow() which is virtual (and will cause a crash).
HWND hMain = mFrameWnd ? mFrameWnd : mWnd;
HWND hMain = GetMainWindow();
if (hMain) {
DEBUGFOCUS(Destroy);
if (hMain == WinQueryFocus(HWND_DESKTOP)) {
@ -505,8 +522,19 @@ NS_METHOD nsWindow::Destroy()
// Standard Window Operations
//=============================================================================
// This can't be inlined in nsWindow.h because it doesn't know about
// GetFrameWnd().
inline HWND nsWindow::GetMainWindow()
{
return mFrame ? mFrame->GetFrameWnd() : mWnd;
}
//-----------------------------------------------------------------------------
// Inline this here for consistency (and a cleaner looking .h).
// static
nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd)
inline nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd)
{
return (nsWindow*)WinQueryWindowPtr(aWnd, QWL_NSWINDOWPTR);
}
@ -514,7 +542,7 @@ nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd)
//-----------------------------------------------------------------------------
// static
PRBool nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow* aPtr)
inline PRBool nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow* aPtr)
{
return WinSetWindowPtr(aWnd, QWL_NSWINDOWPTR, aPtr);
}
@ -525,7 +553,7 @@ nsIWidget* nsWindow::GetParent()
{
// if this window isn't supposed to have a parent or it doesn't have
// a parent, or if it or its parent is being destroyed, return null
if (mIsTopWidgetWindow || mIsDestroying || mOnDestroyCalled ||
if (mFrame || mIsDestroying || mOnDestroyCalled ||
!mParent || mParent->mIsDestroying) {
return 0;
}
@ -555,10 +583,12 @@ NS_METHOD nsWindow::IsEnabled(PRBool* aState)
}
//-----------------------------------------------------------------------------
// nsFrameWindow overrides this
NS_METHOD nsWindow::Show(PRBool aState)
{
if (mFrame) {
return mFrame->Show(aState);
}
if (mWnd) {
if (aState) {
// don't try to show new windows (e.g. the Bookmark menu)
@ -828,15 +858,21 @@ void nsWindow::Scroll(const nsIntPoint& aDelta,
// Window Positioning
//=============================================================================
// For toplevel windows, mBounds contains the dimensions of the client
// window. os2FrameWindow's "override" returns the size of the frame.
NS_METHOD nsWindow::GetBounds(nsIntRect& aRect)
{
if (mFrame) {
return mFrame->GetBounds(aRect);
}
aRect = mBounds;
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsFrameWindow overrides this method. Since it is only invoked on toplevel
// windows, this implementation for child windows should never get called.
// Since mBounds contains the dimensions of the client, os2FrameWindow
// doesn't have to provide any special handling for this method.
NS_METHOD nsWindow::GetClientBounds(nsIntRect& aRect)
{
@ -865,14 +901,14 @@ nsIntPoint nsWindow::WidgetToScreenOffset()
// ptl is in this window's space
void nsWindow::NS2PM(POINTL& ptl)
{
ptl.y = GetClientHeight() - ptl.y - 1;
ptl.y = mBounds.height - ptl.y - 1;
}
// rcl is in this window's space
void nsWindow::NS2PM(RECTL& rcl)
{
LONG height = rcl.yTop - rcl.yBottom;
rcl.yTop = GetClientHeight() - rcl.yBottom;
rcl.yTop = mBounds.height - rcl.yBottom;
rcl.yBottom = rcl.yTop - height;
}
@ -882,7 +918,7 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl)
if (mParent) {
mParent->NS2PM(ptl);
} else {
HWND hParent = WinQueryWindow(GetMainWindow(), QW_PARENT);
HWND hParent = WinQueryWindow(mWnd, QW_PARENT);
SWP swp;
WinQueryWindowPos(hParent, &swp);
ptl.y = swp.cy - ptl.y - 1;
@ -893,9 +929,8 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl)
NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
{
if (mWindowType == eWindowType_toplevel ||
mWindowType == eWindowType_dialog) {
SetSizeMode(nsSizeMode_Normal);
if (mFrame) {
return mFrame->Move(aX, aY);
}
Resize(aX, aY, mBounds.width, mBounds.height, PR_FALSE);
return NS_OK;
@ -905,6 +940,9 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
if (mFrame) {
return mFrame->Resize(aWidth, aHeight, aRepaint);
}
Resize(mBounds.x, mBounds.y, aWidth, aHeight, aRepaint);
return NS_OK;
}
@ -914,6 +952,10 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
if (mFrame) {
return mFrame->Resize(aX, aY, aWidth, aHeight, aRepaint);
}
// For mWnd & eWindowType_child set the cached values upfront, see bug 286555.
// For other mWnd types we defer transfer of values to mBounds to
// WinSetWindowPos(), see bug 391421.
@ -943,7 +985,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY,
&ptl, 1);
}
if (!WinSetWindowPos(GetMainWindow(), 0, ptl.x, ptl.y, aWidth, aHeight,
if (!WinSetWindowPos(mWnd, 0, ptl.x, ptl.y, aWidth, aHeight,
SWP_MOVE | SWP_SIZE) && aRepaint) {
WinInvalidateRect(mWnd, 0, FALSE);
}
@ -1183,277 +1225,57 @@ HWND nsWindow::GetPluginClipWindow(HWND aParentWnd)
// Top-level (frame window) Operations
//=============================================================================
// When a window gets the focus, call nsFrameWindow's version of this
// When a window gets the focus, call os2FrameWindow's version of this
// method. It will fire an NS_ACTIVATE event on the top-level widget
// if appropriate.
void nsWindow::ActivateTopLevelWidget()
{
nsWindow* top = static_cast<nsWindow*>(GetTopLevelWidget());
if (top) {
top->ActivateTopLevelWidget();
if (mFrame) {
mFrame->ActivateTopLevelWidget();
} else {
nsWindow* top = static_cast<nsWindow*>(GetTopLevelWidget());
if (top && top->mFrame) {
top->mFrame->ActivateTopLevelWidget();
}
}
return;
}
//-----------------------------------------------------------------------------
// Maximize, minimize or restore the window. When the frame has its
// controls, this method is advisory because the min/max/restore has
// already occurred. Only when the frame is in kiosk/fullscreen mode
// does it perform the minimize or restore
// All of these methods are inherently toplevel-only, and are in fact
// only invoked on toplevel widgets. If they're invoked on a child
// window, there's an error upstream.
NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode)
{
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED);
PRInt32 previousMode;
GetSizeMode(&previousMode);
// save the new state
nsresult rv = nsBaseWidget::SetSizeMode(aMode);
// Minimized windows would get restored involuntarily if we fired an
// NS_ACTIVATE when the user clicks on them. Instead, we defer the
// activation event until the window has explicitly been restored.
if (previousMode == nsSizeMode_Minimized && previousMode != aMode) {
DEBUGFOCUS(deferred NS_ACTIVATE);
ActivateTopLevelWidget();
}
// nothing to do in these cases
if (!NS_SUCCEEDED(rv) || !mChromeHidden || aMode == nsSizeMode_Maximized) {
return rv;
}
ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
// act on the request if the frame isn't already in the requested state
if (aMode == nsSizeMode_Minimized) {
if (!(ulStyle & WS_MINIMIZED)) {
WinSetWindowPos(mFrameWnd, HWND_BOTTOM, 0, 0, 0, 0,
SWP_MINIMIZE | SWP_ZORDER | SWP_DEACTIVATE);
}
} else
if (ulStyle & (WS_MAXIMIZED | WS_MINIMIZED)) {
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE);
}
return NS_OK;
NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED);
return mFrame->SetSizeMode(aMode);
}
//-----------------------------------------------------------------------------
// Hide or show the frame & its controls (titlebar, minmax, etc.).
NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide)
{
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED);
// Putting a maximized window into fullscreen mode causes multiple
// problems if it's later minimized & then restored. To avoid them,
// restore maximized windows before putting them in fullscreen mode.
if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MAXIMIZED) {
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_NOREDRAW);
}
HWND hParent;
if (aShouldHide) {
hParent = HWND_OBJECT;
mChromeHidden = PR_TRUE;
} else {
hParent = mFrameWnd;
mChromeHidden = PR_FALSE;
}
// Hide or show the frame controls.
HWND hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
if (hControl) {
WinSetParent(hControl, hParent, FALSE);
}
hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu");
if (hControl) {
WinSetParent(hControl, hParent, FALSE);
}
hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax");
if (hControl) {
WinSetParent(hControl, hParent, FALSE);
}
// Modify the frame style, then advise it of the changes.
if (aShouldHide) {
ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
WinSetProperty(mFrameWnd, "ulStyle", (PVOID)ulStyle, 0);
WinSetWindowULong(mFrameWnd, QWL_STYLE, ulStyle & ~FS_SIZEBORDER);
WinSendMsg(mFrameWnd, WM_UPDATEFRAME, 0, 0);
} else {
ULONG ulStyle = (ULONG)WinQueryProperty(mFrameWnd, "ulStyle");
WinSetWindowULong(mFrameWnd, QWL_STYLE, ulStyle);
WinSendMsg(mFrameWnd, WM_UPDATEFRAME,
MPFROMLONG(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX), 0);
}
return NS_OK;
NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED);
return mFrame->HideWindowChrome(aShouldHide);
}
//-----------------------------------------------------------------------------
// On OS/2, if you pass a titlebar > 512 characters, it doesn't display at all.
// We are going to limit our titlebars to 256 just to be on the safe side.
#define MAX_TITLEBAR_LENGTH 256
NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
{
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED);
PRUnichar* uchtemp = ToNewUnicode(aTitle);
for (PRUint32 i = 0; i < aTitle.Length(); i++) {
switch (uchtemp[i]) {
case 0x2018:
case 0x2019:
uchtemp[i] = 0x0027;
break;
case 0x201C:
case 0x201D:
uchtemp[i] = 0x0022;
break;
case 0x2014:
uchtemp[i] = 0x002D;
break;
}
}
nsAutoCharBuffer title;
PRInt32 titleLength;
WideCharToMultiByte(0, uchtemp, aTitle.Length(), title, titleLength);
if (titleLength > MAX_TITLEBAR_LENGTH) {
title[MAX_TITLEBAR_LENGTH] = '\0';
}
WinSetWindowText(mFrameWnd, title.Elements());
// If the chrome is hidden, set the text of the titlebar directly
if (mChromeHidden) {
HWND hTitleBar = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar");
WinSetWindowText(hTitleBar, title.Elements());
}
nsMemory::Free(uchtemp);
return NS_OK;
NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED);
return mFrame->SetTitle(aTitle);
}
//-----------------------------------------------------------------------------
// This implementation guarantees that sysmenus & minimized windows
// will always have some icon other than the sysmenu default.
NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec)
{
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED);
static HPOINTER hDefaultIcon = 0;
HPOINTER hWorkingIcon = 0;
// Assume the given string is a local identifier for an icon file.
nsCOMPtr<nsILocalFile> iconFile;
ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"),
getter_AddRefs(iconFile));
// if the file was found, try to use it
if (iconFile) {
nsCAutoString path;
iconFile->GetNativePath(path);
if (mFrameIcon) {
WinFreeFileIcon(mFrameIcon);
}
mFrameIcon = WinLoadFileIcon(path.get(), FALSE);
hWorkingIcon = mFrameIcon;
}
// if that doesn't work, use the app's icon (let's hope it can be
// loaded because nobody should have to look at SPTR_APPICON - ugggh!)
if (!hWorkingIcon) {
if (!hDefaultIcon) {
hDefaultIcon = WinLoadPointer(HWND_DESKTOP, 0, 1);
if (!hDefaultIcon) {
hDefaultIcon = WinQuerySysPointer(HWND_DESKTOP, SPTR_APPICON, FALSE);
}
}
hWorkingIcon = hDefaultIcon;
}
WinSendMsg(mFrameWnd, WM_SETICON, (MPARAM)hWorkingIcon, (MPARAM)0);
return NS_OK;
NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED);
return mFrame->SetIcon(aIconSpec);
}
//-----------------------------------------------------------------------------
// Constrain a potential move to fit onscreen.
NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop,
PRInt32* aX, PRInt32* aY)
{
NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED);
// do we have enough info to do anything
PRBool doConstrain = PR_FALSE;
// get our playing field. use the current screen, or failing
// that for any reason, use device caps for the default screen.
RECTL screenRect;
nsCOMPtr<nsIScreenManager> screenmgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
if (screenmgr) {
nsCOMPtr<nsIScreen> screen;
PRInt32 left, top, width, height;
// zero size rects confuse the screen manager
width = mBounds.width > 0 ? mBounds.width : 1;
height = mBounds.height > 0 ? mBounds.height : 1;
screenmgr->ScreenForRect(*aX, *aY, width, height,
getter_AddRefs(screen));
if (screen) {
screen->GetAvailRect(&left, &top, &width, &height);
screenRect.xLeft = left;
screenRect.xRight = left+width;
screenRect.yTop = top;
screenRect.yBottom = top+height;
doConstrain = PR_TRUE;
}
}
#define kWindowPositionSlop 100
if (doConstrain) {
if (aAllowSlop) {
if (*aX < screenRect.xLeft - mBounds.width + kWindowPositionSlop) {
*aX = screenRect.xLeft - mBounds.width + kWindowPositionSlop;
} else
if (*aX >= screenRect.xRight - kWindowPositionSlop) {
*aX = screenRect.xRight - kWindowPositionSlop;
}
if (*aY < screenRect.yTop) {
*aY = screenRect.yTop;
} else
if (*aY >= screenRect.yBottom - kWindowPositionSlop) {
*aY = screenRect.yBottom - kWindowPositionSlop;
}
} else {
if (*aX < screenRect.xLeft) {
*aX = screenRect.xLeft;
} else
if (*aX >= screenRect.xRight - mBounds.width) {
*aX = screenRect.xRight - mBounds.width;
}
if (*aY < screenRect.yTop) {
*aY = screenRect.yTop;
} else
if (*aY >= screenRect.yBottom - mBounds.height) {
*aY = screenRect.yBottom - mBounds.height;
}
}
}
return NS_OK;
NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED);
return mFrame->ConstrainPosition(aAllowSlop, aX, aY);
}
//=============================================================================
@ -2143,7 +1965,7 @@ MRESULT nsWindow::ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2)
isDone = DispatchScrollEvent(msg, mp1, mp2);
break;
// Do not act on WM_ACTIVATE - it is handled by nsFrameWindow.
// Do not act on WM_ACTIVATE - it is handled by os2FrameWindow.
// case WM_ACTIVATE:
// break;
@ -2220,7 +2042,6 @@ void nsWindow::OnDestroy()
}
//-----------------------------------------------------------------------------
// nsFrameWindow overrides this.
PRBool nsWindow::OnReposition(PSWP pSwp)
{
@ -2297,7 +2118,7 @@ PRBool nsWindow::OnPaint()
// build XP rect from in-ex window rect
nsIntRect rect;
rect.x = rcl.xLeft;
rect.y = GetClientHeight() - rcl.yTop;
rect.y = mBounds.height - rcl.yTop;
rect.width = rcl.xRight - rcl.xLeft;
rect.height = rcl.yTop - rcl.yBottom;
event.rect = &rect;

Просмотреть файл

@ -46,16 +46,33 @@
//=============================================================================
/*
* nsWindow derives from nsIWidget via nsBaseWindow, and is created when
* NS_CHILD_CID is specified. It is used for widgets that are either
* children of other widgets or are popups (standalone windows such as
* menus that float above other widgets).
*
* nsWindow derives from nsIWidget via nsBaseWindow. With the aid
* of a helper class (os2FrameWindow) and a subclass (nsChildWindow),
* it implements the functionality of both toplevel and child widgets.
*
* Top-level widgets (windows surrounded by a frame with a titlebar, etc.)
* are implemented by nsFrameWindow which is a subclass of nsWindow. Many
* nsWindow methods operate on both child & top-level windows. Where the
* two categories require differing implementations, these methods rely on
* a flag or on virtual helper methods to produce the correct result.
* are created when NS_WINDOW_CID is used to identify the type of object
* needed. Child widgets (windows that either are children of other windows
* or are popups such as menus) are created when NS_CHILD_CID is specified.
* Since Mozilla expects these to be different classes, NS_CHILD_CID is
* mapped to a subclass (nsChildWindow) which acts solely as a wrapper for
* nsWindow and adds no functionality.
*
* While most of the methods inherited from nsIWidget are generic, some
* apply only to toplevel widgets (e.g. setting a title or icon). The
* nature of toplevel windows on OS/2 with their separate frame & client
* windows introduces the need for additional toplevel-specific methods,
* as well as for special handling in otherwise generic methods.
*
* Rather than incorporating these toplevel functions into the body of
* the class, nsWindow delegates them to a helper class, os2FrameWindow.
* An instance of this class is created when nsWindow is told to create
* a toplevel native window and is destroyed in nsWindow's destructor.
* The class's methods operate exclusively on the frame window and never
* deal with the frame's client other than to create it. Similarly,
* nsWindow never operates on frame windows except for a few trivial
* methods (e.g. Enable()). Neither class accesses the other's data
* though, of necessity, both call the other's methods.
*
*/
//=============================================================================
@ -123,18 +140,12 @@ extern "C" {
//#define DEBUG_FOCUS
#ifdef DEBUG_FOCUS
#define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \
(int)this, mWnd, mWindowIdentifier)
#else
#define DEBUGFOCUS(what)
#endif
//-----------------------------------------------------------------------------
// Forward declarations
class imgIContainer;
class gfxOS2Surface;
class os2FrameWindow;
MRESULT EXPENTRY fnwpNSWindow(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
@ -215,11 +226,11 @@ protected:
// nsWindow
static void InitGlobals();
virtual nsresult CreateWindow(nsWindow* aParent,
nsresult CreateWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
PRUint32 aStyle);
virtual HWND GetMainWindow() const {return mWnd;}
nsWidgetInitData* aInitData);
HWND GetMainWindow();
static nsWindow* GetNSWindowPtr(HWND aWnd);
static PRBool SetNSWindowPtr(HWND aWnd, nsWindow* aPtr);
void NS2PM(POINTL& ptl);
@ -228,7 +239,7 @@ protected:
void ActivatePlugin(HWND aWnd);
void SetPluginClipRegion(const Configuration& aConfiguration);
HWND GetPluginClipWindow(HWND aParentWnd);
virtual void ActivateTopLevelWidget();
void ActivateTopLevelWidget();
HBITMAP DataToBitmap(PRUint8* aImageData, PRUint32 aWidth,
PRUint32 aHeight, PRUint32 aDepth);
HBITMAP CreateBitmapRGB(PRUint8* aImageData,
@ -240,7 +251,7 @@ protected:
static PRBool RollupOnButtonDown(ULONG aMsg);
static void RollupOnFocusLost(HWND aFocus);
MRESULT ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2);
virtual PRBool OnReposition(PSWP pNewSwp);
PRBool OnReposition(PSWP pNewSwp);
PRBool OnPaint();
PRBool OnMouseChord(MPARAM mp1, MPARAM mp2);
PRBool OnDragDropMsg(ULONG msg, MPARAM mp1, MPARAM mp2,
@ -264,16 +275,16 @@ protected:
PRInt16 aButton = nsMouseEvent::eLeftButton);
PRBool DispatchActivationEvent(PRUint32 aEventType);
PRBool DispatchScrollEvent(ULONG msg, MPARAM mp1, MPARAM mp2);
virtual PRInt32 GetClientHeight() {return mBounds.height;}
friend MRESULT EXPENTRY fnwpNSWindow(HWND hwnd, ULONG msg,
MPARAM mp1, MPARAM mp2);
friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg,
MPARAM mp1, MPARAM mp2);
friend class os2FrameWindow;
HWND mWnd; // window handle
nsWindow* mParent; // parent widget
PRBool mIsTopWidgetWindow; // is nsFrameWindow class?
os2FrameWindow* mFrame; // ptr to os2FrameWindow helper object
PRInt32 mWindowState; // current nsWindowState_* value
PRBool mIsDestroying; // in destructor
PRBool mInSetFocus; // prevent recursive calls
@ -283,14 +294,24 @@ protected:
HPOINTER mCssCursorHPtr; // created by SetCursor(imgIContainer*)
nsCOMPtr<imgIContainer> mCssCursorImg;// saved by SetCursor(imgIContainer*)
nsRefPtr<gfxOS2Surface> mThebesSurface;
HWND mFrameWnd; // frame window handle
HPOINTER mFrameIcon; // current frame icon
PRBool mChromeHidden; // are frame controls hidden?
#ifdef DEBUG_FOCUS
int mWindowIdentifier; // a serial number for each new window
#endif
};
//=============================================================================
// nsChildWindow
//=============================================================================
// This only purpose of this subclass is to map NS_CHILD_CID to
// some class other than nsWindow which is mapped to NS_WINDOW_CID.
class nsChildWindow : public nsWindow {
public:
nsChildWindow() {}
~nsChildWindow() {}
};
#endif // _nswindow_h
//=============================================================================

Просмотреть файл

@ -0,0 +1,745 @@
/* vim: set sw=2 sts=2 et cin: */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** 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):
* Rich Walsh <dragtext@e-vertise.com>
*
* 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 are
* Copyright (c) International Business Machines Corporation, 2000
*
*/
//=============================================================================
#include "nsWindow.h"
#include "os2FrameWindow.h"
#include "nsIRollupListener.h"
#include "nsIScreenManager.h"
#include "nsOS2Uni.h"
//-----------------------------------------------------------------------------
// External Variables (in nsWindow.cpp)
extern nsIRollupListener* gRollupListener;
extern nsIWidget* gRollupWidget;
extern PRBool gRollupConsumeRollupEvent;
extern PRUint32 gOS2Flags;
#ifdef DEBUG_FOCUS
extern int currentWindowIdentifier;
#endif
//-----------------------------------------------------------------------------
// Debug
#ifdef DEBUG_FOCUS
#define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \
(int)this, mFrameWnd, mWindowIdentifier)
#else
#define DEBUGFOCUS(what)
#endif
//=============================================================================
// os2FrameWindow Setup
//=============================================================================
os2FrameWindow::os2FrameWindow(nsWindow* aOwner)
{
mOwner = aOwner;
mFrameWnd = 0;
mTitleBar = 0;
mSysMenu = 0;
mMinMax = 0;
mSavedStyle = 0;
mFrameIcon = 0;
mChromeHidden = PR_FALSE;
mNeedActivation = PR_FALSE;
mPrevFrameProc = 0;
mFrameBounds = nsIntRect(0, 0, 0, 0);
}
//-----------------------------------------------------------------------------
os2FrameWindow::~os2FrameWindow()
{
if (mFrameIcon) {
WinFreeFileIcon(mFrameIcon);
mFrameIcon = 0;
}
}
//-----------------------------------------------------------------------------
// Create frame & client windows for an os2FrameWindow object; return the
// handle of the client window. This is the only method that manipulates
// the client window - all other operations on it are handled by nsWindow.
HWND os2FrameWindow::CreateFrameWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
nsWindowType aWindowType,
nsBorderStyle aBorderStyle)
{
// Create a frame window with a MozillaWindowClass window as its client.
HWND hClient;
PRUint32 fcfFlags = GetFCFlags(aWindowType, aBorderStyle);
mFrameWnd = WinCreateStdWindow(HWND_DESKTOP,
0,
(ULONG*)&fcfFlags,
kWindowClassName,
"Title",
WS_CLIPCHILDREN,
NULLHANDLE,
0,
&hClient);
if (!mFrameWnd) {
return 0;
}
// Hide from the Window List until shown.
SetWindowListVisibility(PR_FALSE);
// This prevents a modal dialog from being covered by its disabled parent.
if (aParentWnd != HWND_DESKTOP) {
WinSetOwner(mFrameWnd, aParentWnd);
}
// Get the frame control HWNDs for use by fullscreen mode.
mTitleBar = WinWindowFromID(mFrameWnd, FID_TITLEBAR);
mSysMenu = WinWindowFromID(mFrameWnd, FID_SYSMENU);
mMinMax = WinWindowFromID(mFrameWnd, FID_MINMAX);
// Calc the size of a frame needed to contain a client area of the
// specified width & height. Without this, eWindowType_dialog windows
// will be truncated (toplevel windows will still display correctly).
RECTL rcl = {0, 0, aRect.width, aRect.height};
WinCalcFrameRect(mFrameWnd, &rcl, FALSE);
mFrameBounds = nsIntRect(aRect.x, aRect.y,
rcl.xRight-rcl.xLeft, rcl.yTop-rcl.yBottom);
// Move & resize the frame.
PRInt32 pmY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
- mFrameBounds.y - mFrameBounds.height;
WinSetWindowPos(mFrameWnd, 0, mFrameBounds.x, pmY,
mFrameBounds.width, mFrameBounds.height,
SWP_SIZE | SWP_MOVE);
// Store the client's bounds. For windows with resizable borders,
// the width includes the width of the frame controls (minmax, etc.).
SWP swp;
WinQueryWindowPos(hClient, &swp);
mOwner->SetBounds(nsIntRect(swp.x, mFrameBounds.height - swp.y - swp.cy,
swp.cx, swp.cy));
// Subclass the frame.
mPrevFrameProc = WinSubclassWindow(mFrameWnd, fnwpFrame);
WinSetWindowPtr(mFrameWnd, QWL_USER, this);
DEBUGFOCUS(Create os2FrameWindow);
return hClient;
}
//-----------------------------------------------------------------------------
PRUint32 os2FrameWindow::GetFCFlags(nsWindowType aWindowType,
nsBorderStyle aBorderStyle)
{
PRUint32 style = FCF_TITLEBAR | FCF_SYSMENU | FCF_TASKLIST |
FCF_CLOSEBUTTON | FCF_NOBYTEALIGN | FCF_AUTOICON;
if (aWindowType == eWindowType_dialog) {
if (aBorderStyle == eBorderStyle_default) {
style |= FCF_DLGBORDER;
} else {
style |= FCF_SIZEBORDER | FCF_MINMAX;
}
}
else {
style |= FCF_SIZEBORDER | FCF_MINMAX;
}
if (gOS2Flags & kIsDBCS) {
style |= FCF_DBE_APPSTAT;
}
if (aWindowType == eWindowType_invisible) {
style &= ~FCF_TASKLIST;
}
if (aBorderStyle != eBorderStyle_default &&
aBorderStyle != eBorderStyle_all) {
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_resizeh)) {
style &= ~FCF_SIZEBORDER;
style |= FCF_DLGBORDER;
}
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_border)) {
style &= ~(FCF_DLGBORDER | FCF_SIZEBORDER);
}
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_title)) {
style &= ~(FCF_TITLEBAR | FCF_TASKLIST);
}
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_close)) {
style &= ~FCF_CLOSEBUTTON;
}
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & (eBorderStyle_menu | eBorderStyle_close))) {
style &= ~FCF_SYSMENU;
}
// Looks like getting rid of the system menu also does away
// with the close box. So, we only get rid of the system menu
// if you want neither it nor the close box.
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_minimize)) {
style &= ~FCF_MINBUTTON;
}
if (aBorderStyle == eBorderStyle_none ||
!(aBorderStyle & eBorderStyle_maximize)) {
style &= ~FCF_MAXBUTTON;
}
}
return style;
}
//=============================================================================
// Window Operations
//=============================================================================
// For frame windows, 'Show' is equivalent to 'Show & Activate'.
nsresult os2FrameWindow::Show(PRBool aState)
{
PRUint32 ulFlags;
if (!aState) {
ulFlags = SWP_HIDE | SWP_DEACTIVATE;
} else {
ulFlags = SWP_SHOW | SWP_ACTIVATE;
PRUint32 ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
PRInt32 sizeMode;
mOwner->GetSizeMode(&sizeMode);
if (!(ulStyle & WS_VISIBLE)) {
if (sizeMode == nsSizeMode_Maximized) {
ulFlags |= SWP_MAXIMIZE;
} else if (sizeMode == nsSizeMode_Minimized) {
ulFlags |= SWP_MINIMIZE;
} else {
ulFlags |= SWP_RESTORE;
}
} else if (ulStyle & WS_MINIMIZED) {
if (sizeMode == nsSizeMode_Maximized) {
ulFlags |= SWP_MAXIMIZE;
} else {
ulFlags |= SWP_RESTORE;
}
}
}
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, ulFlags);
SetWindowListVisibility(aState);
return NS_OK;
}
//-----------------------------------------------------------------------------
void os2FrameWindow::SetWindowListVisibility(PRBool aState)
{
HSWITCH hswitch = WinQuerySwitchHandle(mFrameWnd, 0);
if (hswitch) {
SWCNTRL swctl;
WinQuerySwitchEntry(hswitch, &swctl);
swctl.uchVisibility = aState ? SWL_VISIBLE : SWL_INVISIBLE;
swctl.fbJump = aState ? SWL_JUMPABLE : SWL_NOTJUMPABLE;
WinChangeSwitchEntry(hswitch, &swctl);
}
}
//=============================================================================
// Window Positioning
//=============================================================================
nsresult os2FrameWindow::GetBounds(nsIntRect& aRect)
{
aRect = mFrameBounds;
return NS_OK;
}
//-----------------------------------------------------------------------------
nsresult os2FrameWindow::Move(PRInt32 aX, PRInt32 aY)
{
aY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - mFrameBounds.height - aY;
WinSetWindowPos(mFrameWnd, 0, aX, aY, 0, 0, SWP_MOVE);
return NS_OK;
}
//-----------------------------------------------------------------------------
nsresult os2FrameWindow::Resize(PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
WinSetWindowPos(mFrameWnd, 0, 0, 0, aWidth, aHeight, SWP_SIZE);
return NS_OK;
}
//-----------------------------------------------------------------------------
nsresult os2FrameWindow::Resize(PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
aY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - aY - aHeight;
WinSetWindowPos(mFrameWnd, 0, aX, aY, aWidth, aHeight, SWP_MOVE | SWP_SIZE);
return NS_OK;
}
//=============================================================================
// Top-level (frame window) Operations
//=============================================================================
// When WM_ACTIVATE is received with the "gaining activation" flag set,
// the frame's wndproc sets mNeedActivation. Later, when an nsWindow
// gets a WM_FOCUSCHANGED msg with the "gaining focus" flag set, it
// invokes this method on os2FrameWindow to fire an NS_ACTIVATE event.
void os2FrameWindow::ActivateTopLevelWidget()
{
// Don't fire event if we're minimized or else the window will
// be restored as soon as the user clicks on it. When the user
// explicitly restores it, SetSizeMode() will call this method.
if (mNeedActivation) {
PRInt32 sizeMode;
mOwner->GetSizeMode(&sizeMode);
if (sizeMode != nsSizeMode_Minimized) {
mNeedActivation = PR_FALSE;
DEBUGFOCUS(NS_ACTIVATE);
mOwner->DispatchActivationEvent(NS_ACTIVATE);
}
}
return;
}
//-----------------------------------------------------------------------------
// Maximize, minimize or restore the window. When the frame has its
// controls, this method is advisory because the min/max/restore has
// already occurred. Only when the frame is in kiosk/fullscreen mode
// does it perform the minimize or restore
nsresult os2FrameWindow::SetSizeMode(PRInt32 aMode)
{
PRInt32 previousMode;
mOwner->GetSizeMode(&previousMode);
// save the new state
nsresult rv = mOwner->nsBaseWidget::SetSizeMode(aMode);
// Minimized windows would get restored involuntarily if we fired an
// NS_ACTIVATE when the user clicks on them. Instead, we defer the
// activation event until the window has explicitly been restored.
if (previousMode == nsSizeMode_Minimized && previousMode != aMode) {
DEBUGFOCUS(deferred NS_ACTIVATE);
ActivateTopLevelWidget();
}
// nothing to do in these cases
if (!NS_SUCCEEDED(rv) || !mChromeHidden || aMode == nsSizeMode_Maximized) {
return rv;
}
ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
// act on the request if the frame isn't already in the requested state
if (aMode == nsSizeMode_Minimized) {
if (!(ulStyle & WS_MINIMIZED)) {
WinSetWindowPos(mFrameWnd, HWND_BOTTOM, 0, 0, 0, 0,
SWP_MINIMIZE | SWP_ZORDER | SWP_DEACTIVATE);
}
} else
if (ulStyle & (WS_MAXIMIZED | WS_MINIMIZED)) {
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// Hide or show the frame & its controls (titlebar, minmax, etc.).
nsresult os2FrameWindow::HideWindowChrome(PRBool aShouldHide)
{
// Putting a maximized window into fullscreen mode causes multiple
// problems if it's later minimized & then restored. To avoid them,
// restore maximized windows before putting them in fullscreen mode.
if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MAXIMIZED) {
WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_NOREDRAW);
}
HWND hParent;
if (aShouldHide) {
hParent = HWND_OBJECT;
mChromeHidden = PR_TRUE;
} else {
hParent = mFrameWnd;
mChromeHidden = PR_FALSE;
}
// Hide or show the frame controls.
WinSetParent(mTitleBar, hParent, FALSE);
WinSetParent(mSysMenu, hParent, FALSE);
WinSetParent(mMinMax, hParent, FALSE);
// Modify the frame style, then advise it of the changes.
if (aShouldHide) {
mSavedStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE);
WinSetWindowULong(mFrameWnd, QWL_STYLE, mSavedStyle & ~FS_SIZEBORDER);
WinSendMsg(mFrameWnd, WM_UPDATEFRAME, 0, 0);
} else {
WinSetWindowULong(mFrameWnd, QWL_STYLE, mSavedStyle);
WinSendMsg(mFrameWnd, WM_UPDATEFRAME,
MPFROMLONG(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX), 0);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// On OS/2, if you pass a titlebar > 512 characters, it doesn't display at all.
// We are going to limit our titlebars to 256 just to be on the safe side.
#define MAX_TITLEBAR_LENGTH 256
nsresult os2FrameWindow::SetTitle(const nsAString& aTitle)
{
PRUnichar* uchtemp = ToNewUnicode(aTitle);
for (PRUint32 i = 0; i < aTitle.Length(); i++) {
switch (uchtemp[i]) {
case 0x2018:
case 0x2019:
uchtemp[i] = 0x0027;
break;
case 0x201C:
case 0x201D:
uchtemp[i] = 0x0022;
break;
case 0x2014:
uchtemp[i] = 0x002D;
break;
}
}
nsAutoCharBuffer title;
PRInt32 titleLength;
WideCharToMultiByte(0, uchtemp, aTitle.Length(), title, titleLength);
if (titleLength > MAX_TITLEBAR_LENGTH) {
title[MAX_TITLEBAR_LENGTH] = '\0';
}
WinSetWindowText(mFrameWnd, title.Elements());
// If the chrome is hidden, set the text of the titlebar directly
if (mChromeHidden) {
WinSetWindowText(mTitleBar, title.Elements());
}
nsMemory::Free(uchtemp);
return NS_OK;
}
//-----------------------------------------------------------------------------
// This implementation guarantees that sysmenus & minimized windows
// will always have some icon other than the sysmenu default.
nsresult os2FrameWindow::SetIcon(const nsAString& aIconSpec)
{
static HPOINTER hDefaultIcon = 0;
HPOINTER hWorkingIcon = 0;
// Assume the given string is a local identifier for an icon file.
nsCOMPtr<nsILocalFile> iconFile;
mOwner->ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"),
getter_AddRefs(iconFile));
// if the file was found, try to use it
if (iconFile) {
nsCAutoString path;
iconFile->GetNativePath(path);
if (mFrameIcon) {
WinFreeFileIcon(mFrameIcon);
}
mFrameIcon = WinLoadFileIcon(path.get(), FALSE);
hWorkingIcon = mFrameIcon;
}
// if that doesn't work, use the app's icon (let's hope it can be
// loaded because nobody should have to look at SPTR_APPICON)
if (!hWorkingIcon) {
if (!hDefaultIcon) {
hDefaultIcon = WinLoadPointer(HWND_DESKTOP, 0, 1);
if (!hDefaultIcon) {
hDefaultIcon = WinQuerySysPointer(HWND_DESKTOP, SPTR_APPICON, FALSE);
}
}
hWorkingIcon = hDefaultIcon;
}
WinSendMsg(mFrameWnd, WM_SETICON, (MPARAM)hWorkingIcon, (MPARAM)0);
return NS_OK;
}
//-----------------------------------------------------------------------------
// Constrain a potential move to fit onscreen.
nsresult os2FrameWindow::ConstrainPosition(PRBool aAllowSlop,
PRInt32* aX, PRInt32* aY)
{
// do we have enough info to do anything
PRBool doConstrain = PR_FALSE;
// get our playing field. use the current screen, or failing
// that for any reason, use device caps for the default screen.
RECTL screenRect;
nsCOMPtr<nsIScreenManager> screenmgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
if (screenmgr) {
nsCOMPtr<nsIScreen> screen;
PRInt32 left, top, width, height;
// zero size rects confuse the screen manager
width = mFrameBounds.width > 0 ? mFrameBounds.width : 1;
height = mFrameBounds.height > 0 ? mFrameBounds.height : 1;
screenmgr->ScreenForRect(*aX, *aY, width, height,
getter_AddRefs(screen));
if (screen) {
screen->GetAvailRect(&left, &top, &width, &height);
screenRect.xLeft = left;
screenRect.xRight = left+width;
screenRect.yTop = top;
screenRect.yBottom = top+height;
doConstrain = PR_TRUE;
}
}
#define kWindowPositionSlop 100
if (doConstrain) {
if (aAllowSlop) {
if (*aX < screenRect.xLeft - mFrameBounds.width + kWindowPositionSlop) {
*aX = screenRect.xLeft - mFrameBounds.width + kWindowPositionSlop;
} else
if (*aX >= screenRect.xRight - kWindowPositionSlop) {
*aX = screenRect.xRight - kWindowPositionSlop;
}
if (*aY < screenRect.yTop) {
*aY = screenRect.yTop;
} else
if (*aY >= screenRect.yBottom - kWindowPositionSlop) {
*aY = screenRect.yBottom - kWindowPositionSlop;
}
} else {
if (*aX < screenRect.xLeft) {
*aX = screenRect.xLeft;
} else
if (*aX >= screenRect.xRight - mFrameBounds.width) {
*aX = screenRect.xRight - mFrameBounds.width;
}
if (*aY < screenRect.yTop) {
*aY = screenRect.yTop;
} else
if (*aY >= screenRect.yBottom - mFrameBounds.height) {
*aY = screenRect.yBottom - mFrameBounds.height;
}
}
}
return NS_OK;
}
//=============================================================================
// os2FrameWindow's Window Procedure
//=============================================================================
// 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 (gRollupListener && 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 (!nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) {
gRollupListener->Rollup(PR_UINT32_MAX, nsnull);
}
}
}
os2FrameWindow* pFrame = (os2FrameWindow*)WinQueryWindowPtr(hwnd, QWL_USER);
return pFrame->ProcessFrameMessage(msg, mp1, mp2);
}
//-----------------------------------------------------------------------------
// Process messages from the frame
MRESULT os2FrameWindow::ProcessFrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mresult = 0;
PRBool isDone = PR_FALSE;
switch (msg) {
case WM_WINDOWPOSCHANGED: {
PSWP pSwp = (PSWP)mp1;
if (pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE)) {
POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy };
ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y;
mFrameBounds.x = ptl.x;
mFrameBounds.y = ptl.y;
mOwner->DispatchMoveEvent(ptl.x, ptl.y);
}
// Save the frame's bounds, then call the default wndproc
// so the client can handle its WM_WINDOWPOSCHANGED msg now.
if (pSwp->fl & SWP_SIZE && !(pSwp->fl & SWP_MINIMIZE)) {
mFrameBounds.width = pSwp->cx;
mFrameBounds.height = pSwp->cy;
mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
isDone = PR_TRUE;
}
if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) {
nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, mOwner);
if (pSwp->fl & SWP_MAXIMIZE) {
event.mSizeMode = nsSizeMode_Maximized;
} else if (pSwp->fl & SWP_MINIMIZE) {
event.mSizeMode = nsSizeMode_Minimized;
} else {
event.mSizeMode = nsSizeMode_Normal;
}
mOwner->InitEvent(event);
mOwner->DispatchWindowEvent(&event);
}
break;
}
// A frame window in kiosk/fullscreen mode must have its frame
// controls reattached before it's minimized & detached after it's
// restored. If this doesn't happen at the correct times, clicking
// on the icon won't restore it, the sysmenu will have the wrong
// items, and/or the minmax button will have the wrong buttons.
case WM_ADJUSTWINDOWPOS:
if (mChromeHidden && ((PSWP)mp1)->fl & SWP_MINIMIZE) {
WinSetParent(mTitleBar, mFrameWnd, TRUE);
WinSetParent(mSysMenu, mFrameWnd, TRUE);
WinSetParent(mMinMax, mFrameWnd, TRUE);
}
break;
case WM_ADJUSTFRAMEPOS:
if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) {
WinSetParent(mTitleBar, HWND_OBJECT, TRUE);
WinSetParent(mSysMenu, HWND_OBJECT, TRUE);
WinSetParent(mMinMax, HWND_OBJECT, TRUE);
}
break;
case WM_DESTROY:
DEBUGFOCUS(frame WM_DESTROY);
WinSubclassWindow(mFrameWnd, mPrevFrameProc);
WinSetWindowPtr(mFrameWnd, QWL_USER, 0);
break;
case WM_INITMENU:
// If we are in fullscreen/kiosk mode, disable maximize menu item.
if (mChromeHidden &&
SHORT1FROMMP(mp1) == SC_SYSMENU &&
WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
MENUITEM menuitem;
WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM,
MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem));
mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE);
isDone = PR_TRUE;
}
break;
case WM_SYSCOMMAND:
// If we are in fullscreen/kiosk mode, don't honor maximize requests.
if (mChromeHidden &&
SHORT1FROMMP(mp1) == SC_MAXIMIZE &&
WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) {
isDone = PR_TRUE;
}
break;
// When the frame is activated, set a flag to be acted on after
// PM has finished changing focus. When deactivated, dispatch
// the event immediately because it doesn't affect the focus.
case WM_ACTIVATE:
DEBUGFOCUS(WM_ACTIVATE);
if (mp1) {
mNeedActivation = PR_TRUE;
} else {
mNeedActivation = PR_FALSE;
DEBUGFOCUS(NS_DEACTIVATE);
mOwner->DispatchActivationEvent(NS_DEACTIVATE);
// Prevent the frame from automatically focusing any window
// when it's reactivated. Let moz set the focus to avoid
// having non-widget children of plugins focused in error.
WinSetWindowULong(mFrameWnd, QWL_HWNDFOCUSSAVE, 0);
}
break;
}
if (!isDone) {
mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2);
}
return mresult;
}
//=============================================================================

Просмотреть файл

@ -0,0 +1,109 @@
/* vim: set sw=2 sts=2 et cin: */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** 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):
* Rich Walsh <dragtext@e-vertise.com>
*
* 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 ***** */
//=============================================================================
/*
* os2FrameWindow is a helper class instantiated by nsWindow to handle
* operations that are specific to OS/2 frame windows. It never references
* the frame's client window except to create it. See nsWindow.h for details.
* Note: nsWindow.h must be #included in *.cpp before #including this file.
*
*/
//=============================================================================
#ifndef _os2framewindow_h
#define _os2framewindow_h
//=============================================================================
// os2FrameWindow
//=============================================================================
class os2FrameWindow
{
public:
os2FrameWindow(nsWindow* aOwner);
~os2FrameWindow();
HWND CreateFrameWindow(nsWindow* aParent,
HWND aParentWnd,
const nsIntRect& aRect,
nsWindowType aWindowType,
nsBorderStyle aBorderStyle);
PRUint32 GetFCFlags(nsWindowType aWindowType,
nsBorderStyle aBorderStyle);
nsresult Show(PRBool aState);
void SetWindowListVisibility(PRBool aState);
nsresult GetBounds(nsIntRect& aRect);
nsresult Move(PRInt32 aX, PRInt32 aY);
nsresult Resize(PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint);
nsresult Resize(PRInt32 aX, PRInt32 aY, PRInt32 w, PRInt32 h,
PRBool aRepaint);
void ActivateTopLevelWidget();
nsresult SetSizeMode(PRInt32 aMode);
nsresult HideWindowChrome(PRBool aShouldHide);
nsresult SetTitle(const nsAString& aTitle);
nsresult SetIcon(const nsAString& aIconSpec);
nsresult ConstrainPosition(PRBool aAllowSlop,
PRInt32* aX, PRInt32* aY);
MRESULT ProcessFrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2);
HWND GetFrameWnd() {return mFrameWnd;}
friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg,
MPARAM mp1, MPARAM mp2);
protected:
nsWindow * mOwner; // the nsWindow that created this instance
HWND mFrameWnd; // the frame's window handle
HWND mTitleBar; // the frame controls that have
HWND mSysMenu; // to be hidden or shown when
HWND mMinMax; // HideWindowChrome() is called
PRUint32 mSavedStyle; // frame style saved by HideWindowChrome()
HPOINTER mFrameIcon; // current frame icon
PRBool mChromeHidden; // are frame controls hidden?
PRBool mNeedActivation; // triggers activation when focus changes
PFNWP mPrevFrameProc; // the frame's original wndproc
nsIntRect mFrameBounds; // the frame's location & dimensions
};
#endif //_os2framewindow_h
//=============================================================================